题目描述
编写一个程序,找到两个单链表相交的起始节点。
如下面的两个链表:
示例 1:
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skiha = 2, skihb = 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], skiha = 3, skihb = 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], skiha = 3, skihb = 2
输出:null
输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skiha 和 skihb 可以是任意值。
解释:这两个链表不相交,因此返回 null。
解法:双指针(C++)
算法的思路很简单,就是:
初始化 ha = headA, hb = headB,开始遍历。
若A链短,ha会先到达链表尾,当ha到达末尾时,重置ha为headB;同样的,当hb到达末尾时,重置hb为headA。当ha与hb相遇时,必然就是两个链表的交点。
为什么这么做可以做呢?
因为这样的一个遍历过程,对ha而言,走过的路程即为a+c+b,对hb而言,即为b+c+a,显然a+c+b = b+c+a,这就是该算法的核心原理。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *ha = headA, *hb = headB;
while(ha != hb)
{
ha = ha==NULL?headB:ha->next;
hb = hb==NULL?headA:hb->next;
}
return ha;
}
};