160. Intersection of Two Linked Lists
来源:互联网 发布:nba2k17帅气捏脸数据 编辑:程序博客网 时间:2024/06/15 05:46
做这道题目的时候顺带复习了一下找带环单链表的环入口,在第二种解法中将作解释。
描述:
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
意:找到其中的相交节点(修改一下也可以叫做环的入口节点),很明显,图中的入口是c1.
解法1
分析:
我们可以将这两条链表看成是两条平行的线段,其中后面的一段线段是一定相同的,只不过前面一段有长有短:
a1 a2 c1 c2 c3 b1 b2 b3 c1 c2 c3//很容易看出来其实就是c1前面的一部分元素个数不同
那么我们可以这样来使得它们同步起来:
1.先让a,b两条链走完统计出两条链表的长度为a1,a2
2.找出其中长的一条链,让它先往前走abs(a1-a2)个节点,这时候将长链表中多余的元素走完了
3.另外一条链也同时开始走,这时候两条链表剩余的长度是一样的,走到第一个相等的节点就是入口节点了。
C++
class Solution {public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { ListNode* A = headA; ListNode* B = headB; int a = 0; int b = 0; while(A){ a++; A = A->next; } while(B){ b++; B = B->next; } //这里需要加一个判断两条链表没有交点的情况,注意 if(A != B){return NULL;} int Max = max(a,b) - min(a,b); //或者abs(a-b),一样 if(a>b){ while(Max){ headA = headA->next; Max--; } } else{ while(Max){ headB = headB->next; Max--; } } while(headA != headB){ headA = headA->next; headB = headB->next; } return headA;} };
python:
class Solution(object): def getIntersectionNode(self, headA, headB): A = headA B = headB a = 0 b = 0 while A is not None: a += 1 A = A.next while B is not None: b += 1 B = B.next if A != B: return None Max = abs(a-b) if a > b: while Max: headA = headA.next Max -= 1 else: while Max: headB = headB.next Max -= 1 while headA != headB: headA = headA.next headB = headB.next return headA
解法二:
分析:
这道题目其实和我们之前做过的一道判断单链表是否有环很相像,我们只需要稍微构造一下即可还原那道题目的样子。
比如还是上面的例子
A: a1 → a2 ↘ c1 → c2 → c3 ↗ B: b1 → b2 → b3//我们这做,将c3 -> next = b1
那么就变成如下的图了:
这样就构成一个环了,关于环我们可以了解到:使用两个指针,一快一慢,我们能根据两个指针是否相交来判断这个链表是不是有环,但是要找到环的入口呢?这里我们需要通过一些推导:
参考了这篇博客
大致过程咱们也来推导一下,加深自己的理解:
这里是黑色的部分是慢指针走过的路径,红色部分是快指针绕环经过的路径:
假设
L1:平行线的长度,o点到m点L2:整个环的长度L_m_n:入口点m和相交点n的距离,按着箭头指示的方向走slow_len : 慢指针走过的距离k : 快指针走过的圈数我们能得到几个公式:1.L1 + L_m_n = slow_len2.slow_len = L2 - L_m_n3.L1 + k*L2 + L_m_n = slow_len综合这3个等式可以得到:L1 = k*L2 - L_m_n = (k-1)L2 + (L2 - L_m_n)这个式子拿到图中就是:L1的距离 = 环的整数倍数(k-1倍) + 交点与环入口的距离,更具体一点:就是红色线段和平行线段等长也就是说,找到交点之后,再往前走L1步就能到达环的入口,这时候让链表头和这个交点同时向前走,如果是有环,则必然能相交,否则为nullptr。
C++
//时间复杂度是O(n),空间复杂度是O(1)class Solution {public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { ListNode* head = headA; if (headA == NULL || headB == NULL) return NULL; while(headA->next){ headA = headA->next; } headA->next = headB; ListNode* res = iscycle(head); headA->next = nullptr; return res; } ListNode* iscycle(ListNode* head){ ListNode* slow = head; ListNode* fast = head; while(slow && fast){ slow = slow->next; fast = fast->next; if(fast){ fast = fast->next; } if(fast == slow){ break; } } if (fast == nullptr){return nullptr;} slow = head; while (slow != fast) { slow = slow->next; fast = fast->next; } return fast; }};
python:
class Solution(object): def getIntersectionNode(self, headA, headB): if not headA or not headB: return None ptr = headA while ptr.next != None: ptr = ptr.next ptr.next = headB res = self.iscycle(headA) ptr.next = None return res def iscycle(self,head): slow = head fast = head while slow and fast: slow = slow.next fast = fast.next if fast: fast = fast.next if fast == slow: break if fast == None: return None slow = head while slow != fast: slow = slow.next fast = fast.next return fast
0 0
- [LeetCode]160.Intersection of Two Linked Lists
- LeetCode 160. Intersection of Two Linked Lists
- 【LeetCode】160.Intersection of Two Linked Lists
- [leetcode] 160.Intersection of Two Linked Lists
- 160. Intersection of Two Linked Lists
- 160. Intersection of Two Linked Lists
- [LeetCode]160. Intersection of Two Linked Lists
- 160. Intersection of Two Linked Lists
- 160. Intersection of Two Linked Lists
- LeetCode--160. Intersection of Two Linked Lists
- 160. Intersection of Two Linked Lists
- LeetCode 160. Intersection of Two Linked Lists
- 160. Intersection of Two Linked Lists
- 160. Intersection of Two Linked Lists
- 160. Intersection of Two Linked Lists
- 【LeetCode】160. Intersection of Two Linked Lists
- 160. Intersection of Two Linked Lists
- 160. Intersection of Two Linked Lists
- linux线程栈的若干思考
- java 小技巧 利用for循环反转字符串
- 为什么sql里面not in后面的子查询如果有记录为NULL的,主查询就查不到记录
- Maven的settings.xml文件结构之servers
- 【mark】第一次打卡,mark一下进度
- 160. Intersection of Two Linked Lists
- java枚举类使用备忘
- 学习编程是一个漫长的历程
- 优美的日期选择器
- 函数指针
- ubuntu14.04 为例 samba服务配置
- Android支持HTML标签
- Design下FloatingActionButton的简单使用
- 树状数组理解