【算法】链表:160.相交链表(easy)+双指针

 系列专栏

《分治》

《模拟》

《Linux》


目录

1、题目链接

2、题目介绍

3、解法(双指针) 

 返回结果

算法正确性

时间复杂度

4、代码


1、题目链接

160. 相交链表 - 力扣(LeetCode)

2、题目介绍

3、解法(双指针) 

推荐题解:题解 - 力扣(LeetCode)

该题解中的图示过程非常清晰!

这道题目,类似于检测两个链表中是否存在环。--->针对有环问题 ---> 我们通常使用快慢指针解决。

那么本题,使用的就是快慢指针的一个变形,找到两个链表的相交点。

设「第一个公共节点」为 node ,「链表 headA」的节点数量为 a ,「链表 headB」的节点数量为 b ,「两链表的公共尾部」的节点数量为 c ,则有:
 

头节点 headA 到 node 前,共有 a−c 个节点;
头节点 headB 到 node 前,共有 b−c 个节点;


考虑构建两个节点指针 A​ , B 分别指向两链表头节点 headA , headB ,做如下操作:

  • 指针 A 先遍历完链表 headA ,再开始遍历链表 headB ,当走到 node 时,共走步数为:a+(b−c)
  • 指针 B 先遍历完链表 headB ,再开始遍历链表 headA ,当走到 node 时,共走步数为:b+(a−c)

如下式所示,此时指针 A , B 重合,这是因为两个指针都遍历了相同的节点数(包括重复遍历的部分),并有两种情况:

a+(b−c)=b+(a−c)

  • 若两链表 有 公共尾部 (即 c>0 ) :指针 A , B 同时指向「第一个公共节点」node 。
  • 若两链表 无 公共尾部 (即 c=0 ) :指针 A , B 同时指向 null 。

 返回结果

返回 A(或 B,因为它们此时是相同的)作为相交节点的指针。

如果 A 和 B 没有相遇(都为 null 或指向不同的节点),则返回 null。但在这个算法中,由于我们是在两个链表之间循环遍历,所以它们要么相遇,要么在原始链表上同时到达末尾(然后重新遍历另一个链表),这种情况在逻辑上被视为不相交,因此实际上我们不需要显式地检查 null。

        

算法正确性

该算法的正确性基于这样一个事实:

如果两个链表相交,那么从两个链表的头节点出发,分别遍历到相交节点的路径长度之差一定等于两个链表长度之差。

当我们让一个指针到达链表末尾后重新指向另一个链表的头节点时,我们实际上是在“补齐这个长度差。

因此,两个指针最终会在相交节点上相遇。

时间复杂度

由于每个节点最多被访问两次(一次在其原始链表中,一次在另一个链表中),所以时间复杂度为 O(m + n),其中 m 和 n 分别是两个链表的长度。

空间复杂度

我们只使用了两个指针,所以空间复杂度为 O(1)。 

4、代码

/**
 * 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) {
        //a+b-c
        //a-c+b
        //有公共的结点,c>0,
        ListNode* pa = headA;
        ListNode* pb = headB;
        while (pa != pb)
        {
            if (pa == NULL)
                pa = headB;
            else
                pa = pa->next;

            if (pb == NULL)
                pb = headA;
            else
                pb = pb->next;
        }
        return pa;
    }
};


💗感谢阅读!💗

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值