【算法训练】剑指offer#52 两个链表的第一个公共节点
一、描述
两个链表的第一个公共节点
输入两个链表,找出它们的第一个公共节点。
如下面的两个链表:
在节点 c1 开始相交。
示例 1:
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
示例 2:
输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Reference of the node with value = 2
输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
示例 3:
输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
解释:这两个链表不相交,因此返回 null。
二、思路
- 取出两个链表中的所有value并存入两个list中,之后注意比较list中的值,存在相等就输出,没有就返回None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
# 如果存在空链表,就直接返回None
if not headA or not headB: return None
# 用于遍历链表
valueListA, valueListB = headA, headB
# 用于存储两个链表中的value
listA, listB = [], []
# 遍历并将value存入两个list中
while valueListA:
listA.append(valueListA.val)
valueListA = valueListA.next
while valueListB:
listB.append(valueListB.val)
valueListB = valueListB.next
# 找相等的value
for i in listA:
if i in listB:
return i
return None
- 然后发现理解错题意了(明明是题说的不明白吧...),题的意思应该是返回第一个公共节点,而不是返回值,所以最简单的话,就循环遍历好了
- 仔细想了想还是不对,如果这样的话是没有办法确保相等节点是第一个公共节点的,比如[4,1,8,4,5], [5,0,1,8,4,5]返回的将是4
- 我觉得可以将两个链表进行逆序,然后对产生的两个新链表进行遍历,当出现不相等节点时,前一个结点就是第一个公共节点(可这样时间复杂度就大了吧....)
- 终于想到了....如果两个链表存在公共节点,那么两个链表应该是从尾端对齐的,也就是说,公共节点应该从两个链表长度差的节点开始一一比较,用符号表示的话,链表A,B的长度分别为lengthA,lengthB,则应该从较长链表的第|lengthA-lengthB|位开始比较(唉,这样还需要知道两个链表的长度)
三、解题
class ListNode:
def __init__(self, x):
self.val = x
self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
# 如果存在空链表,就直接返回None
if not headA or not headB: return None
# 用于遍历链表
listA, listB = headA, headB
# 两个链表长度
lengthA, lengthB = 1, 1
# 获取两个链表的长度
while listA:
listA = listA.next
lengthA += 1
while listB:
listB = listB.next
lengthB += 1
# 用于遍历链表
listA, listB = headA, headB
if lengthA > lengthB:
# 开始比较的位置
judgeLoc = lengthA - lengthB
while judgeLoc != 0 :
listA = listA.next
judgeLoc -= 1
else:
# 开始比较的位置
judgeLoc = lengthB - lengthA
while judgeLoc != 0 :
listB = listB.next
judgeLoc -= 1
# 此时两个链表处于对齐的状态
while listA:
# 如果节点相等,则返回该公共节点
if listA == listB:
return listA
listA = listA.next
listB = listB.next
# 如果没有公共节点,则返回None
return None