题目描述
输入两个链表,找出它们的第一个公共结点。
思路
方法一:两个有公共节点的链表是Y字型的结构,自公共节点后是重合的。可以借助两个栈先存储链表的节点。然后两个栈每次出栈一个节点,如果是重合节点,那么这两个节点是相等的。所以最后一个相等的节点就是第一个公共节点。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
# write code here
if not pHead1 or not pHead2:
return None
stack1 = []
stack2 = []
while pHead1:
stack1.append(pHead1)
pHead1 = pHead1.next
while pHead2:
stack2.append(pHead2)
pHead2 = pHead2.next
res = None
while stack1 and stack2:
p1 = stack1.pop()
p2 = stack2.pop()
if p1 == p2:
res = p1
else:
break
return res
方法二:先遍历两个链表,统计长度aa 和bb 。让长链表先走|a−b||a−b| 步,公共节点肯定是存在于后面部分中。然后再对两个链表遍历匹配,遇到的第一个相同节点就是公共节点。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
# write code here
if not pHead1 or not pHead2:
return None
l1 = 0
l2 = 0
h1 = pHead1 #在计算长度的时候要用一个中间链表来计算,不能改变原链表的值
h2 = pHead2 #在计算长度的时候要用一个中间链表来计算,不能改变原链表的值
while h1:
l1 += 1
h1 = h1.next
while h2:
l2 += 1
h2 = h2.next
if l1 > l2:
for i in range(l1-l2):
pHead1 = pHead1.next #这个时候才能改变原链表的值
elif l1 < l2:
for i in range(l2-l1):
pHead2 = pHead2.next
while pHead1 and pHead2:
if pHead1 == pHead2:
return pHead1
else:
pHead1 = pHead1.next
pHead2 = pHead2.next
return None
方法三:时间复杂度和上述代码相同,都需要遍历链表(1+公共节点之前的长度/总长度)
遍,但短的代码长度,解题思路跟方法二也是一样的,但是更少的变量,更巧妙的代码运用,真的是很厉害啊!
def FindFirstCommonNode(self, pHead1, pHead2):
p1, p2 = pHead1, pHead2
while p1 != p2:
p1 = p1.next if p1 != None else pHead2
p2 = p2.next if p2 != None else pHead1
return p1
假设P2首先为None,则P1剩下要走的长度为(L1-L2)
此时P2=pHead1,即等于较长的那个链表,继续跟着P1一起走完(L1-L2),相当于先把pHead1和pHead2之间相差的距离走完
P1走完后,P1=pHead2,这个时候P2和P1剩下的长度相同。(和方法二的思路一样)