1. 题目
输入两个链表,找出它们的第一个公共节点。
2. 解题思路
详情见 图解 双指针法,浪漫相遇
由于链表A和链表B长度不一定相同,而二者相交之后的链表都是相同的,因此这个题的
难点在于A和B并不同步,所以造成无法比较两个链表中的节点是否相同。
2.1 渣渣思路
发现了上面的关键点之后,就写出了
3.1
的代码,思路如下:
1)分别遍历A和B,得到链表的长度差diff;
2)让长的链表先走diff步,然后两个链表再同时往下走,这样两者就是同步的了,可以进行比较了;
3)返回第一个相同的节点,即第一个交点。
2.2 最佳思路
画图更容易理解
两个指针 p 和 q,分别走A+B 和B+A,总长度是一样的,所以使得后面p和q是同步走的,就可以进行比较了。
1)p遍历链表A,q遍历链表B;
2)当p遍历到A的末尾后,再遍历B;
3)当q遍历到B的末尾后,再遍历A;
4)返回第一个交点。
3. 代码实现
3.1 渣渣解法
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
"""
因为链表的后部是一致的,所以A和B链表长度的差异,也就是在公共节点之前那部分的长度差异,只要两个指针能够同步前进,就能找到公共节点
难点在于:若两个链表长度不一样的话,二者不会同时到达第一个公共节点,造成无法比对节点。
"""
length_a = 0
length_b = 0
# 1.遍历链表A,得到链表A长度
temp = headA
while temp:
length_a += 1
temp = temp.next
# 2.遍历链表B,得到链表B长度
temp = headB
while temp:
length_b += 1
temp = temp.next
# 3. 消去两个链表的差值,使得同步检查两个链表
difference = length_a - length_b
if length_a > length_b: # 让headA先走difference步,否则headB先走difference步,使得二者同步
while difference:
headA = headA.next
difference -= 1
else:
difference = -1 * difference
while difference:
headB = headB.next
difference -= 1
while headA:
if headA == headB:
return headA
headA = headA.next
headB = headB.next
return
3.2 最优解法
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
node1, node2 = headA, headB
while node1 != node2:
node1 = node1.next if node1 else headB
node2 = node2.next if node2 else headA
return node1
作者:z1m
链接:https://leetcode-cn.com/problems/liang-ge-lian-biao-de-di-yi-ge-gong-gong-jie-dian-lcof/solution/shuang-zhi-zhen-fa-lang-man-xiang-yu-by-ml-zimingm/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
4. 总结
链表中的操作,大致为一下几种:
- 双指针(同速走,倍速走,相差k步走);
- 创建伪节点;
- 改变链接,改变元素值;
- 消除长度差。
5. 参考文献
[1] 剑指offer丛书
[2] 剑指Offer——名企面试官精讲典型编程题