剑指 Offer 52. 两个链表的第一个公共节点

题目

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fLPBJ3T5-1596254281830)(https://note.youdao.com/yws/api/personal/file/02D79F3A436A4DB49750D7F006A78463?method=download&shareKey=acc40a409765c61c3d6cce68d77690a8)]

在这里插入图片描述

在这里插入图片描述

解题代码初版

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        unordered_set<ListNode*> set;
        ListNode* tmp1 = headA, * tmp2 = headB;
        while(tmp1 != NULL){
            set.insert(tmp1);
            tmp1 = tmp1->next;
        }
        while(tmp2 != NULL){
            if(set.find(tmp2) != set.end()) return tmp2;
            tmp2 = tmp2->next; 
        }
        return NULL;
    }
};
解题思路

运用集合。

集合小特点:不能有重复的元素,无序。

  1. 遍历链表A,并存入set中。
  2. 遍历链表B,边遍历边在set中查找是否有相同的元素。
语法点

集合的定义

unordered_set<ListNode*> set;

集合的插入

set.insert(tmp1);

集合的find()函数

if(set.find(tmp2) != set.end()) return tmp2;

集合的count()函数

// 由于集合的count只能取1和0,因此可以用来判断是否有相同元素。
//(用来查找set中某个某个键值出现的次数。这个函数在set并不是很实用,因为一个键值在set只可能出现0或1次,这样就变成了判断某一键值是否在set出现过了。)

if(set.count(hB) == 1) return hB;

在这里插入图片描述

别人的解法(优化)

作者:腐烂的橘子

我们使用两个指针 node1,node2 分别指向两个链表 headA,headB 的头结点,然后同时分别逐结点遍历,当 node1 到达链表 headA 的末尾时,重新定位到链表 headB 的头结点;当 node2 到达链表 headB 的末尾时,重新定位到链表 headA 的头结点。

这样,当它们相遇时,所指向的结点就是第一个公共结点。

注意点
  • 两个链表长度分别为L1+C、L2+C, C为公共部分的长度,按照楼主的做法: 第一个人走了L1+C步后,回到第二个人起点走L2步;第2个人走了L2+C步后,回到第一个人起点走L1步。 当两个人走的步数都为L1+L2+C时就两个家伙就相爱了)
  • 两链表不相交时,由于行程一样长,最终会同时走到对方链表的终点,同时出现null,此时满足pA = pB循环终止
  • 语法nullptr
C++ 98标准期间,用NULL
C++11 标准期间,用nullptr,专用于初始化空类型指针
总之在 C++11 标准下,相比 NULL 和 0,使用 nullptr 初始化空指针可以令我们编写的程序更加健壮。
也就是说nullptr是后来。
  • 语法
node1 = node1 != NULL ? node1->next : headB;

如果node1不为空,则执行node1->next;

如果node1为空,则执行headB
在这里插入图片描述
动图可访问下面链接:https://leetcode-cn.com/problems/liang-ge-lian-biao-de-di-yi-ge-gong-gong-jie-dian-lcof/solution/shuang-zhi-zhen-fa-lang-man-xiang-yu-by-ml-zimingm/

代码
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *node1 = headA;
        ListNode *node2 = headB;
        
        while (node1 != node2) {
            node1 = node1 != NULL ? node1->next : headB;
            node2 = node2 != NULL ? node2->next : headA;
        }
        return node1;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值