@R星校长
已知两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null
。
杰哥我用白话翻译过来:
链表A
和链表B
相交于C节点
,我们返回C节点
的地址
,如果两个链表之间没有交点,程序返回null
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
杰哥我用白话翻译过来:
不能删除节点
、添加节点
或是改变节点内的数据
。
本题当中有多种解法,实现算法的时候,我们应该尽量使算法的时间复杂度为 O ( n ) O(n) O(n)
,空间复杂度为 O ( 1 ) O(1) O(1)
我们来看一个例子:
示例 1:
输入: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出: Intersected at '8'
解释: 相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。 从各自的表头开始算起,。 在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
杰哥我用白话翻译过来:
链表 A
为 [4,1,8,4,5]
,链表 B
为 [5,0,1,8,4,5]
,两个链表此时相交于值为8
的节点,我们应将该节点的地址返回
/**
* Definition for singly-linked list.
* struct ListNode {
* int val; //节点中存储的数据
* ListNode *next; //指向下一个节点的指针
* ListNode(int x) : val(x), next(NULL) {} //构造函数
* };
*/
题目中ListNode
代表链表中的一个节点,val是节点中存储的数据,next
是指向下一个节点的指针。
构造函数ListNode
初始化val
的值为X
,next
赋为空。
我们需要开发求两个链表交点的函数getIntersectionNode
函数传入两个链表的头节点指针headA
与headB
。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB){
}
};
如果两个链表有交点,那么函数返回相交节点的地址,否则返回NULL
。
杰哥带你分析题目:
首先可以想到两层循环来直接求解该题问题,用headA
遍历链表A
,对A
当中的每一个节点,使用headB
遍历B
中的每一个节点,并同时检查headB
是否与headA
相同,如果相同,说明找到了两个链表的的交点。
例如,最初headA
指向A
的第一个节点,通过headB
遍历B
中的节点时候并没有发现地址与headA
相同的节点,然后我们向后移动headA
在链表B
中,同样没有找到地址相同的节点,当headA
指向第3
个节点的时候,使用headB
遍历链表B
当中的节点,找到了与headA
地址相同的节点,也就是两链表的交点,此时将它返回即可。
如果两个链表没有交点,那么最终headA
与headB
均会指向NUll
,程序返回NULL
。
假设链表A、B
长度为n
,该方法的时间复杂度为 O ( n 2 ) O(n^2) O(n2),并不是理想的方法,我们再介绍两种更优的算法。
第一种方法,通过