两个链表的第一个公共结点

两个链表的第一个公共结点

http://www.nowcoder.com/questionTerminal/6ab1d9a29e88450685099d45c9e31e46

描述

这是一篇针对初学者的题解
知识点:单链表
难度:一星


题解

题目抽象:给定两个单链表A,B,假设一定含有公共结点,返回第一个公共结点的指针。

方法:双指针法

假如例子如下:
图片说明
显然第一个公共结点为8,但是链表A头结点到8的长度为2,链表B头结点到8的长度为3,显然不好办?
如果我们能够制造一种理想情况,如下:
图片说明
这里先假设链表A头结点与结点8的长度 与 链表B头结点与结点8的长度相等,那么就可以用双指针。

  1. 初始化:指针ta指向链表A头结点,指针tb指向链表B头结点
  2. 如果ta == tb, 说明找到了第一个公共的头结点,直接返回即可。
  3. 否则,ta != tb,则++ta,++tb

所以现在的问题就变成,如何让本来长度不相等的变为相等的?
假设链表A长度为a, 链表B的长度为b,此时a != b
但是,a+b == b+a
因此,可以让a+b作为链表A的新长度,b+a作为链表B的新长度。
如图:
图片说明
这样,长度就一致了,可以用上述的双指针解法了。

代码

class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
        ListNode *ta = pHead1, *tb = pHead2;
        while (ta != tb) {
            ta = ta ? ta->next : pHead2;
            tb = tb ? tb->next : pHead1;
        }
        return ta;
    }
};

时间复杂度:O(m+n), m,n分别为链表A,B的长度,最坏情况下,公共结点为最后一个,需要遍历m+n个结点
空间复杂度:O(1)

全部评论
最后一张图和代码的逻辑其实不太符合,容易让人理解成把链表真的复制一遍黏上去……可以把图修改成虚线,这样误导会少一些吧。毕竟实际上代码只是把第一次遍历求长度差和第二次消去长度差后的双指针遍历用巧妙的方法结合在了一起,并没有实际上的复制和黏合操作。
7 回复 分享
发布于 2020-08-30 23:45
a+b之后,两个链表长度一致,所以有公共节点,返回公共节点,遍历次数<=m+n;无公共节点,尾部nullptr也可以看作虚拟的公共节点,返回虚拟公共节点nullptr,遍历m+n+1次.优秀
4 回复 分享
发布于 2021-05-31 17:08
凭啥不考虑没有公共节点的情况?两个链表就一定相交吗?没相交你不就死循环了?即使你给的测试用例都是有公共节点的,但我觉得还是应该考虑。
4 回复 分享
发布于 2021-01-27 22:38
直接让长的链先走一个差值不就行了...还补充啥
4 回复 分享
发布于 2020-07-25 00:21
虽然很巧妙,但是为了防止没有公共点的情况还是要加一些判断条件(比如另外用两个变量指示每个链的长度,走过len(a)+len(b)以后就break跳出死循环)
3 回复 分享
发布于 2021-08-07 14:30
你这个不对啊,题目没说是一定存在相同节点的
3 回复 分享
发布于 2020-09-09 17:41
不会的同学可以看leetcode 160题
2 回复 分享
发布于 2020-07-15 21:13
假设a链表为单链表b链表为循环链表,且b链表正好比a链表长1,这么写会出错。 在这种情况下,即使ab链表没有公共结点也会,返回值也是true。
1 回复 分享
发布于 2020-10-18 14:31
ta = ta不是永远为true么
2 回复 分享
发布于 2020-07-05 14:30
如果两个链表没有交点,是不是就死循环了
21 回复 分享
发布于 2020-06-19 09:56
误人子弟,公共节点明显是1啊
3 回复 分享
发布于 2020-09-09 15:52
不建议这样写,实际上这样健壮性很弱。如果给的例子没有交点,容易死循环。
2 回复 分享
发布于 2021-04-29 16:26
若无交点,一定能保证满足t1、t2为同时为空跳出循环
1 回复 分享
发布于 2022-02-27 10:24
这个思路太巧妙了,厉害(点赞.jpg)
1 回复 分享
发布于 2021-03-16 17:00
看了代码才知道,是边遍历边复制的,而不是两条都复制好了再遍历。。
1 回复 分享
发布于 2021-03-06 22:33
假设我的测试用例是{1,2,1}{4,5}{6,7},这样是不是就会出问题
点赞 回复 分享
发布于 2024-07-05 11:13 湖南
绝了
点赞 回复 分享
发布于 2022-09-14 21:05 浙江
妙蛙妙蛙
点赞 回复 分享
发布于 2022-03-07 17:40
上面的示意图 调整一下更好理解,前面对齐,后面补a+b的补充,两个重合的部分就是交至处
点赞 回复 分享
发布于 2022-02-12 01:54
秀儿
点赞 回复 分享
发布于 2021-11-21 11:26

相关推荐

07-18 10:39
门头沟学院 Java
点赞 评论 收藏
分享
评论
284
16
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务