阅读目录
题目描述
输入两个链表,找出它们的第一个公共结点
思路和Python实现
思路一:粗暴法:用 set() 或者 dic() 这类用了hash表的,空间占用会比较大(不建议这样做)
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
res_set = set()
while pHead1:
res_set.add(pHead1)
pHead1 = pHead1.next
while pHead2:
if pHead2 in res_set:
return pHead2
pHead2 = pHead2.next
思路二:先找出两个链表的长度差值,让长的先走差值,然后当两者会合时的结点就是公共结点
图2-1
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
# write code here
if pHead1 == pHead2:
return pHead1
len1 = self.get_chain_len(pHead1)
len2 = self.get_chain_len(pHead2)
if len2 > len1: # 哪个长就调换一下顺序
pHead1, pHead2 = pHead2, pHead1
diff = abs(len1 - len2) # 计算差值
while diff > 0: # 让长的链表先走diff步
pHead1 = pHead1.next # 始终用PHead1 来走,上面比较,会找出较长的一个
diff -= 1
while pHead1 != pHead2:
pHead1 = pHead1.next
pHead2 = pHead2.next
return pHead1
def get_chain_len(self, Head):
chain_en = 0
while Head:
chain_en += 1
Head = Head.next
return chain_en
思路三:从尾部向前遍历,找到“最后一个”相同的节点,输出即可。可以利用两个栈来实现
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
# write code here
if pHead1== None or pHead2 == None:
return None
stack1 = []
stack2 = []
p1 = pHead1
while p1 is not None: # 依次将两个链表的所有节点分别压入两个栈中
stack1.append(p1)
p1 = p1.next
p2 = pHead2
while p2 is not None:
stack2.append(p2)
p2 = p2.next
res = None
while len(stack1) > 0 and len(stack2) > 0:
# 从后往前遍历,直到找到两个链表相同的最后一个节点,如果相同的话。
v1 = stack1.pop()
v2 = stack2.pop()
if v1 == v2:
res = v1
else:
break
return res
思路四:再次相遇
- 两个长度不一样的链表 p1 和 p2 (假设 p1更短,p2更长);p1、p2 先不断的各自的往尾结点移动,短的 p1 先指向None,此时让它再次指向长的链表 p2 开头,和还没走完的长链表 p2 同时继续移动,当长链表 p2 指向None时,让它指向短链表p1的开头;不要忘了,短链表在长链表上已经移动了p2-p1 (两者之间的差)的距离,p2 的起始点变成了短链表的起始点,p1在长链表的起始点,已经和短链表的长度一致,所以 p1 p2 一起移动时,再次相遇就是 第一个公共结点了!
- 详细过程 见下图 2-2
class Solution:
def FindFirstCommonNode(self, pHead1, pHead2):
if not pHead1 or not pHead2:
return None
p1 = pHead1 # 新起两个指针,不能把原链表的头部丢失掉
p2 = pHead2
while p1 != p2:
p1 = p1.next if p1 is not None else pHead2 # 当前节点为空,指向另一个链表的头部
p2 = p2.next if p2 is not None else pHead1
return p1
图 2-2