题目描述
给定两个链表,请找它们的交汇点。
注意:
- 如果两个链表不相交,则返回
null
; - 在函数结束时,两个链表必须保持原来的结构;
- 链表中不存在环;
- 你的代码需要的时间复杂度是 $O(n)$,额外的空间复杂度是 $O(1)$;
样例
给定如下两个链表:
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
则交汇点是 c1。
算法
(链表,指针扫描) $O(n)$
这题的思路很巧妙,我们先给出做法,再介绍原理。
算法步骤:
- 用两个指针分别从两个链表头部开始扫描,每次分别走一步;
- 如果指针走到
null
,则从另一个链表头部开始走; - 当两个指针相同时,
- 如果指针不是
null
,则指针位置就是相遇点; - 如果指针是
null
,则两个链表不相交;
- 如果指针不是
此题我们画图讲解,一目了然:
$1$. 两个链表不相交:
$a,b$ 分别代表两个链表的长度,则两个指针分别走 $a+b$ 步后都变成 null
。
$2$. 两个链表相交:
则两个指针分别走 $a+b+c$ 步后在两链表交汇处相遇。
时间复杂度分析:每个指针走的长度不大于两个链表的总长度,所以时间复杂度是 $O(n)$。
C++ 代码
/**
* 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 *p = headA, *q = headB;
while (p != q)
{
if (p) p = p->next;
else p = headB;
if (q) q = q->next;
else q = headA;
}
return p;
}
};
把他们抽象到同一条路上去了hh
太优雅了
unordered_set也能搞定
题目要求:仅用 O(1) 内存的解决方案,不能用哈希
[4,1,8,4,5]
[5,6,1,8,4,5]这个例子里面相交是8而不是1,运行了一下发现1的地址不同,8的地址相同,所以判断这个相等应该指的是地址相同,可是想问一下为什么8的地址就相同而1就不同呢?地址分配是随机的吗?
我觉得是第一个链表中的1是由4指向的,第二个链表中的1是由6指向的。判断相交的话应该是节点的进出都相同吧。
本题lc的输入除了两个链表之外,还有两个数:2, 3,我推测这两个数是指相交的节点在两个链表里的编号。所以本题相交的节点并不是由数值决定的,而是由后面给出的编号决定的。
厉害呀
哈哈
emmmm 时间复杂度最坏情况准确来说应该是O(m+n)吧?m,n为A,B 链表长度
啊这里的 $n$ 表示两个链表的总长度hh
soga!
本来我写的是先计算两个链表的长度,然后让长度长的指针先走完长度差的距离,第一次相遇就是答案了。好像也是总共经历了$2(a+b+c)$步。
不过这样代码复杂度就比较高了,没有这样思路的代码巧妙简洁。
这种做法也是可以的hh
也可以先将链表搞成环 然后按照找环的入口那题的思路 嘿嘿
可以的~不过杀鸡焉用宰牛刀hh
妙啊~!
美啊~美不胜收!妙啊~妙不可言!