剑指offer---两个链表的第一个公共结点

题目描述

输入两个链表,找出它们的第一个公共结点。

struct ListNode {

int val;

struct ListNode *next;

ListNode(int x) :

val(x), next(NULL) {

}

};

class Solution {

public:

ListNode* FindFirstCommonNode(ListNode* pHead1, ListNode* pHead2) {

if (pHead1 == NULL || pHead2 == NULL)

return NULL;

int count1 = 0;

int count2 = 0;

int count = 0;

ListNode *p1 = pHead1;

ListNode *p2 = pHead2;

while (p1)

{

count1++;

p1 = p1->next;

}

while (p2)

{

count2++;

p2 = p2->next;

}

if (count1 >= count2)

{

count = count1 - count2;

p1 = pHead1;

p2 = pHead2;

while (count)

{

p1 = p1->next;

count--;

}

}

else

{

count = count2 - count1;

p1 = pHead1;

p2 = pHead2;

while (count)

{

p2 = p2->next;

count--;

}

}

while (p1 != NULL&&p2 != NULL)

{

if (p1 == p2)

return p1;

else

{

p1 = p1->next;

p2 = p2->next;

}

}



return NULL;

}

};

 之前博客里边介绍过两个链表相交的求法,并且有简单和复杂多种情况,这里是较为简单的情况也就是我们的链表不带环。

https://blog.csdn.net/Hanani_Jia/article/details/79815538  这是我之前所介绍过的链表相交的情况也就是我们这道题的解法。

https://blog.csdn.net/Hanani_Jia/article/details/79832711 这是我们的升级版也就是链表可能会带环的情况,想看升级版的大家可以点进去看,这里我只对简单的情况进行一个介绍。

这是我们两个链表相交的情况,两个链表有个公共部分,我们这里要求的就是我们三个颜色直线相交的位置。我之前的想法是找两个链表相同的的结点,如果两个节点相同就返回当前结点如果不相同就继续往下走,但是这个解决方法是有一个前提的也就是我们两个链表的长度是有一样的,不然就像我们图中一样红色的链表比较长,那我们从链表头开始一个一个对比,如果不一样两个指针都往后移动,但是当我们的绿色的链表已经到了公共部分时红色的链表还是在他自己独有的部分。所以简单的用这种方法是不行的,但是这个思想已经有了我们就要对这种方法进行一个改进,既然红色的长我们就让红色的先走一段,毕竟前边那一部分是两个不重合的部分,是不会存在相同结点的,所以就有了我上边的程序,我们先通过循环来求两个链表的长度,然后找到长的那个链表让他先走一段,走完它长的那一段之后两个链表开始都走,这样如果遇见相同的那个节点就是我们要找的第一个共同结点了。我之前的讲解更详细一些如果这里有看不懂的话可以去看我之前的博客。

  但是在牛客网编程的话一定要看看大家其他人提交的代码,那个才是在牛客网真正刷题的目的。

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

  这是我在其他人提交代码的时候发现的一段,这段代码大家都有很多的争议有说对有说错,我大概看了看大家说的问题之后我认为这段代码没有问题不过很跳跃而已。

 我们既然求相交的结点,那就说几种情况,第一种:两个链表长度相同并且不相交。第二种:两个链表长度相同并且相交。第三种:两个链表长度不相同并且不相交。第四种:两个链表长度不相同并且相交。如果这四种情况他都能很好的解决出来那基本就不存在问题了。我们先说一下三步运算符,如果问好前边的表达式结果是真那么执行冒号前边的语句,如果问号前边是假那就执行冒号后边的语句。  (p1==NULL ? pHead2 : p1->next)拿这个式子来举例,如果p1等于NULL的话那说明式子是真的那就返回pHead2,如果不是空的话那式子就是假那就返回p1->next.

当我们两个链表长度相同时并且不相交两个链表会同时到达我们的结尾,那p1,p2都是空这时候while条件就不成立了,就会推出并且返回我们的p1,也就是NULL,这种情况解决了。我们再看第二种情况如果两个链表长度相同,那就是我上边说的情况如果两个链表长度相同那很好解决就是一个一个去比对就行,在比对的时候两个链表会同时到达我们的相交点,这时候while条件又不符合情况了,这时候返回p1也就是返回我们的相交点,复杂的是我们下边链表长度不同的两种情况。如果我们两个链表长度不相同,这里我们给两个链表假设一个长度

图中的数字就是我们的长度,长的是我们的p1,短的是我们的p2.根据代码中的情况,我们p2走到最后之后因为还没遇到p1等于p2的情况,所以循环继续进行,这时候p2会从p1头开始走,这时候p1还在公共结点倒数第二个位置,因为p1比p2长两个嘛,当p1走到结尾之后会从p2头开始走,p1这时候比p2晚走了两步,但是p2走的是p1表,p1表要比p2表长两步,最终还是会在第一个相遇结点相遇,这时候退出while循环,这里用的思想就是两个指针都走了十二个结点也就是两个指针都走了一个公共部分并且把两个链表前边的部分都走了。

之后就是两个链表长度不相同并且不想交,看看能不能正确退出

这里我们还是假设长的是我们p1,短的是我们的p2,这里其实很简单,这里是怎么走的呢?这里是两个指针都走了16,都走了两个链表的长度最终走到了结尾返回NULL。

所以在我看来这段代码是没有问题的,在牛客网编程还是要多看看大神的代码,看看他们是怎么很简单的去解决问题的。自己的代码量是别人的好几倍....

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值