您的位置:首页 > 编程语言 > C语言/C++

[LeetCode] Intersection of Two Linked Lists

2015-04-12 16:28 246 查看


Intersection of Two Linked Lists

 

Write a program to find the node at which the intersection of two singly linked lists begins.

For example, the following two linked lists:
A:          a1 → a2
↘
c1 → c2 → c3
↗
B:     b1 → b2 → b3


begin to intersect at node c1.

Notes:
If the two linked lists have no intersection at all, return 
null
.
The linked lists must retain their original structure after the function returns.
You may assume there are no cycles anywhere in the entire linked structure.
Your code should preferably run in O(n) time and use only O(1) memory.

解题思路:

1、最naive的办法,就是最每个a的指针,在b里面找,是否与之相同,若找到,则返回,否则返回NULL。这个办法时间复杂度为O(n*m)。不符合要求。

2、可以考虑用set来存储a的每个指针,然后针对每个b的指针,在set中查找。因为set中的查找可以看成是O(1)的,因此时间复杂度为O(n)。但是空间复杂度为O(n),不符合要求。

3、我的办法是,先分别扫描一遍a、b,记录a、b的长度为aLen,bLen。然后从头分别开始扫描,每扫描一个aLen--或bLen--,然后a或b向后移一个。具体是a移呢还是b移呢?这要看aLen大还是bLen大。具体代码如下,代码具有自解释:

/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int aLen = 0, bLen = 0;
ListNode *p, *q;
p=headA;
while(p!=NULL){
aLen++;
p=p->next;
}
p=headB;
while(p!=NULL){
bLen++;
p=p->next;
}
ListNode* result=NULL;
p=headA;
q=headB;
while(p!=NULL&&q!=NULL){
if(p==q){
result=p;
break;
}else{
if(aLen>bLen){
p=p->next;
aLen--;
}else if(aLen<bLen){
q=q->next;
bLen--;
}else{
p=p->next;
q=q->next;
aLen--; //这里减不减都无所谓
bLen--;
}
}
}
return result;
}
};4、看了一下官方的说法,先分别用两个指针pa,pb扫描,先到结尾的序列短(假设为b),将pb指向a的头,继续逐个扫描,当pa到达尾部后,将pa指向b的头。此时pa指向了b的头,pb指向了a中的某个节点,且pb后面未扫描的元素个数等于b链表的长度。此时再分别扫描,遇到pa=pb,则返回。下面是代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* pA=headA, *pB=headB;
while(pA!=NULL&&pB!=NULL){
if(pA==pB){
return pA;
}
pA=pA->next;
pB=pB->next;
}
if(pA==NULL){ //B比A长
pA=headB;
}else{
pB=headA;
}
while(pA!=NULL&&pB!=NULL){
pA=pA->next;
pB=pB->next;
}
if(pA==NULL){ //与之前第20步相反
pA=headB;
}else{
pB=headA;
}
while(pA!=NULL&&pB!=NULL){
if(pA==pB){
return pA;
}
pA=pA->next;
pB=pB->next;
}
return NULL;
}
};上述3、4其实效率是一样的,都分别扫描了两次链表。4可能更快一点,但是方法没有很明白,不容易懂。提交后,发现很多人都比我的效率高呀,不知各位有更好的办法木有?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++ leetcode