02.07.链表相交

记录新手小白做题历程。

题目

题目:

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

图示两个链表在节点 c1 开始相交:

保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。


尝试:

思路:暴力解法,两个循环,一个记录A链的数字,一个移动B链的数字,若两个结点的数字相同,则判断后面的数字是否相同,直至遇见结点。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *p1=headA;
        ListNode *p2=headB;
        int i=0,j=0;
        for(;p1;i++){
            int count=p1->val;//记录p1结点的值
            for(;p2;j++){
                if(count==p2->val){//找到了相同数值的结点,判断后面的链表是否相等
                        ListNode *cur=p2->next;
                        ListNode *cur1=p1->next;
                    while(cur){
                        if(cur->val!=cur1->val){
                            break;
                        }
                        cur=cur->next;
                        cur1=cur1->next;
                    }
                    if(cur==nullptr&&cur1==nullptr)
                        return p2->val;//如果,它们一直交到最后一个结点,找到了
                }
                p2=p2->next;
            }
            p1=p1->next;
            p2=headB;//初始化p2
        }
        return null;
    }
};

代码写出来后显示编译错误。

1.cannot initialize return object of type 'ListNode *' with an lvalue of type 'int' return p2->val 

无法初始化类型为 'ListNode *' 的返回对象,左值类型为 'int' 返回 p2->val

大概意思是说,需要我返回结点但我返回成了Int整型

2.use of undeclared identifier 'null' return null; 使用未声明的标识符"null"返回空

这个返回null是看题解里写的,正确应该是返回nullptr

好了改正之后进行提交,对了44个,错一个。

我不是很理解自己哪个方向出错了,如果这个错了,那其它的不应该对啊,怎么会跳过1 呢

看下别人代码。


正确答案 

官方题解。

lenA, lenB。设重合长度为c。设两者节点总和为sum。设实际总结点数为z。

  • 若有重合,sum! = z

应该有lenA+lenB = sum=z + c;//一个很简单的论证题应该可以想明白的,c被重合了。

双指针遍历时,如果两者有重合点,一定都会走到sum的时候,这个时候正好走到还差C长度的节点上,即sum != z;

  • 若不重合,sum = z;,两个节点都走到空

点击链接

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *A = headA, *B = headB;
        while (A != B) {
            A = A != nullptr ? A->next : headB;//遍历A,A是否等于空。为空就继续遍历B,不为空则继续遍历
            B = B != nullptr ? B->next : headA;//遍历B,与上面一行相似
        }
        return A;
    }
};

看到这个代码量瑟瑟发抖 。

一个指针先遍历A,再遍历B,另一个指针先遍历B,再遍历A,若两者最终相等了,说明两者有交点,若两者最终都没有就是空,不过这个也符合最后返回A的条件,因为A最后遍历为空。

 great,真的很棒。

第二位大佬:

点击链接

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* curA = headA;
        ListNode* curB = headB;
        int lenA = 0, lenB = 0;
        while (curA != NULL) { // 求链表A的长度
            lenA++;
            curA = curA->next;
        }
        while (curB != NULL) { // 求链表B的长度
            lenB++;
            curB = curB->next;
        }
        curA = headA;
        curB = headB;
        // 让curA为最长链表的头,lenA为其长度
        if (lenB > lenA) {
            swap (lenA, lenB);
            swap (curA, curB);
        }
        // 求长度差
        int gap = lenA - lenB;
        // 让curA和curB在同一起点上(末尾位置对齐)
        while (gap--) {
            curA = curA->next;
        }
        // 遍历curA 和 curB,遇到相同则直接返回
        while (curA != NULL) {
            if (curA == curB) {
                return curA;
            }
            curA = curA->next;
            curB = curB->next;
        }
        return NULL;
    }
};

他的写法非常巧妙,在将两个链表取到长度一致的情况下之后,后面若遇到相同的数字则合为同一链表。

不过我觉得不一定啊,遇到一个相同的后面不一定就合成一个链表了。

看来这道题还要再研究研究。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值