题目描述:
编写一个程序,找到两个单链表相交的起始节点。
如下面的两个链表:
在节点 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。
注意:
- 如果两个链表没有交点,返回 null.
- 在返回结果后,两个链表仍须保持原有的结构
- 可假定整个链表结构中没有循环
- 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。
思路:
具有公共节点的链表如下所示:
链表从后往前第一个不同的节点前的那个就是第一个公共节点,但链表从后往前无法遍历,因此可以将链表放入栈中,然后依次出栈并记录当前相同的节点。
- 如果下个节点不同,则输出当前节点为第一个公共节点
- 否则,继续出栈直到碰到第一个彼此不同的节点,输出第一个公共节点
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
def helper(head):
l = []
while head:
l.append(head)
head = head.next
return l
if headA is None or headB is None:
return None
temp = None
l1, l2 = helper(headA), helper(headB)
while l1 and l2:
s1, s2 = l1.pop(), l2.pop()
if s1 != s2:
return temp
else:
temp = s1
return temp
但是上面的解法使用了两个栈来存储两个链表中的元素,此时的空间复杂度为 O ( N ) O(N) O(N),时间复杂度为 O ( N ) O(N) O(N)。
如果想要让空间复杂度控制在 O ( 1 ) O(1) O(1),那么就不能使用额外的空间,只能在链表本身上操作。
- 获取两个链表的长度,同时设置两个指针 p p p和 q q q,并让 p p p指向更长的那个链表, q q q指向较短的那个链表
- 计算长度差 n u m num num,让 p p p多往前走 n u m num num步,然后依次往后找直到找到第一个值相同的结点即第一个公共结点
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
def helper(head):
l = 0
while head:
l += 1
head = head.next
return l
if headA is None or headB is None:
return None
l1, l2 = helper(headA), helper(headB)
if l1 > l2:
p, q = headA, headB
else:
q, p = headA, headB
l = abs(l1 - l2)
while l and p:
p = p.next
l -= 1
while p and q:
if p == q:
return p
else:
p, q = p.next, q.next
return None