Interview----判断两个链表是否相交?
2014-02-28 12:37
267 查看
题目描述:
判断两个单链表是否相交?假设链表没有环。
假如链表有环呢?
1. 假如没有环
那么如果两个链表相交的话,必然最后的节点一定是同一个节点。所以只需要各自扫描一遍链表,找到最后一个节点,比较是否相同即可。
O ( M + N)
2. 可能有环
首先,如何判断是否有环?
采用快慢指针,一个指针一次走两步,一个指针一次走一步,如果链表有环的话,必然最后慢指针会赶上快指针。
复杂度同样是 O ( M + N)。
如果还要求求出 进入环的那个节点: 可以用两个指针,一个从链表head 出发,另一个从刚刚快慢指针的相遇点出发,速度相同。
可以证明,两指针必定在入口处第一次相遇。
根据是否有环,可以分为以下三个 case:
case 1: 都没有环:已经分析
case 2: 都有环: 注意到如果相交,这两个环必定是一模一样的。所以,只要判断是否有一个节点在另一个环中即可。
case 3: 一个有环,一个没有环: 一定不相交
完整代码如下:
判断两个单链表是否相交?假设链表没有环。
假如链表有环呢?
1. 假如没有环
那么如果两个链表相交的话,必然最后的节点一定是同一个节点。所以只需要各自扫描一遍链表,找到最后一个节点,比较是否相同即可。
O ( M + N)
// version 1 // test whether two lists are intersected // assume each list has no circle bool IsIntersectedNoCircle(ListNode *lhs, ListNode *rhs) { if(lhs == NULL || rhs == NULL) return false; ListNode *tail1(lhs); for(; tail1->next; tail1 = tail1->next); ListNode *tail2(lhs); for(; tail2->next; tail2 = tail2->next); return tail1 == tail2; }
2. 可能有环
首先,如何判断是否有环?
采用快慢指针,一个指针一次走两步,一个指针一次走一步,如果链表有环的话,必然最后慢指针会赶上快指针。
复杂度同样是 O ( M + N)。
如果还要求求出 进入环的那个节点: 可以用两个指针,一个从链表head 出发,另一个从刚刚快慢指针的相遇点出发,速度相同。
可以证明,两指针必定在入口处第一次相遇。
// test whether list has a circle // if true, return the enter node // if not, return NULL ListNode* HasCircle(ListNode *list) { if(list == NULL || list->next == NULL) return NULL; // fast/slow pointer method // if circled, slow pointer will catch up with fast one ListNode *fast(list), *slow(list); while(fast) { fast = fast->next; if(fast == NULL) return NULL; fast = fast->next; slow = slow->next; if(fast == slow) break; } assert(fast == NULL || slow == fast); if(fast == NULL) return NULL; // list definitely has a circle // find the enter node // fast and enter will meet at the enter node ListNode *enter(list); while(enter != fast) { enter = enter->next; fast = fast->next; } return enter; }
根据是否有环,可以分为以下三个 case:
case 1: 都没有环:已经分析
case 2: 都有环: 注意到如果相交,这两个环必定是一模一样的。所以,只要判断是否有一个节点在另一个环中即可。
case 3: 一个有环,一个没有环: 一定不相交
// version 2 // assume lists may have a circle inside bool IsIntersectedCircle(ListNode *lhs, ListNode *rhs) { ListNode *enter1(NULL), *enter2(NULL); enter1 = HasCircle(lhs); enter2 = HasCircle(rhs); // case 1: both lists have no circles if(enter1 == NULL && enter2 == NULL) { return IsIntersectedNoCircle(lhs, rhs); } // case 2: each have a circle else if(enter1 && enter2) { ListNode *node(enter1->next); while(node != enter1 && node != enter2){ node = node->next; } return node == enter2; } // case 3: one has a circle, while the other not else { return false; } }
完整代码如下:
// copyright @ L.J.SHOU Feb.27, 2014
// test whether two lists are intersected
#include <iostream>
#include <cassert>
using namespace std;
struct ListNode{
int val;
ListNode *next;
ListNode(int x)
:val(x), next(NULL){}
};
ListNode* HasCircle(ListNode*);
bool IsIntersectedCircle(ListNode*, ListNode*);
// version 1 // test whether two lists are intersected // assume each list has no circle bool IsIntersectedNoCircle(ListNode *lhs, ListNode *rhs) { if(lhs == NULL || rhs == NULL) return false; ListNode *tail1(lhs); for(; tail1->next; tail1 = tail1->next); ListNode *tail2(lhs); for(; tail2->next; tail2 = tail2->next); return tail1 == tail2; }
// version 2 // assume lists may have a circle inside bool IsIntersectedCircle(ListNode *lhs, ListNode *rhs) { ListNode *enter1(NULL), *enter2(NULL); enter1 = HasCircle(lhs); enter2 = HasCircle(rhs); // case 1: both lists have no circles if(enter1 == NULL && enter2 == NULL) { return IsIntersectedNoCircle(lhs, rhs); } // case 2: each have a circle else if(enter1 && enter2) { ListNode *node(enter1->next); while(node != enter1 && node != enter2){ node = node->next; } return node == enter2; } // case 3: one has a circle, while the other not else { return false; } }
// test whether list has a circle // if true, return the enter node // if not, return NULL ListNode* HasCircle(ListNode *list) { if(list == NULL || list->next == NULL) return NULL; // fast/slow pointer method // if circled, slow pointer will catch up with fast one ListNode *fast(list), *slow(list); while(fast) { fast = fast->next; if(fast == NULL) return NULL; fast = fast->next; slow = slow->next; if(fast == slow) break; } assert(fast == NULL || slow == fast); if(fast == NULL) return NULL; // list definitely has a circle // find the enter node // fast and enter will meet at the enter node ListNode *enter(list); while(enter != fast) { enter = enter->next; fast = fast->next; } return enter; }
// destroy list
ListNode* Destroy(ListNode *list)
{
ListNode *next(NULL);
while(list)
{
next = list->next;
delete list;
list = next;
}
return NULL;
}
int main(void)
{
ListNode *list(NULL);
// testing case 1: both have no circles
list = new ListNode(1);
list->next = new ListNode(2);
list->next->next = new ListNode(3);
ListNode *list2 = list->next;
cout << IsIntersectedCircle(list, list2) << endl;
// testing case 2: both have circles
list2 = new ListNode(1);
list2->next = new ListNode(2);
list2->next->next = list->next;
list->next->next->next = list->next;
cout << IsIntersectedCircle(list, list2) << endl;
list->next->next->next = NULL;
list2->next->next = NULL;
// testing case 3: only one has a circle
list->next->next->next = list->next;
cout << IsIntersectedCircle(list, list2) << endl;
list->next->next->next = NULL;
list = Destroy(list);
list2 = Destroy(list2);
return 0;
}
相关文章推荐
- Interview----判断两个链表是否相交?
- 判断两个链表是否相交并找出交点
- 判断两个链表是否相交
- 判断单链表是否有环,如果有找出环的入口位置=>求两个相交链表的交点
- 链表逆序、判断是否有环、求环的起点;两个链表是否相交、交点
- 编程之美-判断两个链表是否相交方法整理
- 判断两个单向链表是否有相交,并找出交点。
- 编程之美-判断两个链表是否相交 (涵其扩展问题)
- 判断单链表是否存在环,判断两个链表是否相交-的相关讨论
- ]数据结构:单链表之判断两个链表是否相交及求交点(带环、不带环)
- 判断单链表是否存在环,判断两个链表是否相交
- 判断链表有环没环及环的入口结点问题 和 判断两个链表是否相交
- 判断单链表是否存在环,判断两个链表是否相交问题详解
- 判断两个单链表是否相交(链表中可能有环的情况下)
- 编程之美--判断两个链表是否相交
- 判断两个链表是否相交
- 编程之美3.6——编程判断两个链表是否相交
- 3.6 判断两个无环链表是否相交 & 找出相交的第一个结点
- C语言强化(七)链表相交问题_4 判断两个有环链表是否相交
- 判断两个链表是否相交