【剑指offer】两个链表的第一个公共结点(python)
纪念一下,第一次一遍过!很棒,加油!
思路是双指针,一个遍历链表1,一个遍历链表2,需要注意的是指针复制的地方,链表2的指针是外部的,不需要复制,遍历到尾部就拉倒了,但是链表1的指针是内部的,需要复制,复制的地方在外循环内、内循环外。
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
#
#
# @param pHead1 ListNode类
# @param pHead2 ListNode类
# @return ListNode类
#
class Solution:
def FindFirstCommonNode(self , pHead1 , pHead2 ):
# write code here
if pHead1 is None or pHead2 is None:
return None
while pHead2 is not None:
p1 = pHead1
while p1 is not None:
if p1.val == pHead2.val:
return p1
else:
p1 = p1.next
pHead2 = pHead2.next
return None好家伙,大神的代码更牛逼。
- 直接用 p1 is not p2 判断两个结点是否相等
- python 三元运算符,“为真时的结果 if 判定条件 else 为假时的结果”
p1 = p1.next if p1 else pHead2
p2 = p2.next if p2 else pHead1
复杂写法就是:
if p1:
p1 = p1.next
else:
p1 = pHead2
if p2:
p2 = p2.next
else:
p2 = pHead1
用两个指针扫描两个链表,最终两个指针到达 null 或者到达公共结点。短链表指针先走完,然后指向长链表,指向长链表指针后走完,指向短链表。所以,第二次走过,一定会在交点相遇。
长度相同有公共结点,第一次就遍历到;没有公共结点,走到尾部NULL相遇,返回NULL,长度不同有公共结点,第一遍差值就出来了,第二遍一起到公共结点;没有公共,一起到结尾NULL。
这里先假设链表A头结点与结点8的长度 与 链表B头结点与结点8的长度相等,那么就可以用双指针。
初始化:指针ta指向链表A头结点,指针tb指向链表B头结点
如果ta == tb, 说明找到了第一个公共的头结点,直接返回即可。
否则,ta != tb,则++ta,++tb
所以现在的问题就变成,如何让本来长度不相等的变为相等的?
假设链表A长度为a, 链表B的长度为b,此时a != b
但是,a+b == b+a
因此,可以让a+b作为链表A的新长度,b+a作为链表B的新长度。
如图:
这样,长度就一致了,可以用上述的双指针解法了。
时间复杂度:O(m+n), m,n分别为链表A,B的长度,最坏情况下,公共结点为最后一个,需要遍历m+n个结点
class Solution:
def FindFirstCommonNode(self , pHead1 , pHead2 ):
p1, p2 = pHead1, pHead2
while p1 is not p2:
p1 = p1.next if p1 else pHead2
p2 = p2.next if p2 else pHead1
return p1 
京公网安备 11010502036488号