两个链表的第一个公共节点(简单难度)

简介: 两个链表的第一个公共节点(简单难度)

题目概述(简单难度)

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


如下面的两个链表:

2.png

在节点 c1 开始相交。

示例 1:

2.png

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA
= 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。


示例 2:

2.png


输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3,
skipB = 1
输出:Reference of the node with value = 2
输入解释:相交节点的值为 2(注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [0,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

示例 3:

2.png


输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB
= 2
输出:null
输入解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。 解释:这两个链表不相交,因此返回 null。


注意:


1:如果两个链表没有交点,返回 null.

2:在返回结果后,两个链表仍须保持原有的结构。

3:可假定整个链表结构中没有循环。

4:程序尽量满足 O(n)时间复杂度,且仅用 O(1) 内存。


附上leetcode链接:

点击此处进入leetcode

附上牛客网链接

点击此处进入牛客网


思路与代码

思路展现

寻找两个链表的第一个公共节点,很多同学会陷入一个误区当中,先来看一个示意图:

2.png

对于上面这个图来说,很多同学会误以为值域为33的这个节点就是我们两个链表的第一个公共节点,但是这是错误的,连我本人第一次做这道题的时候也是这么认为的,原因是链表的第一个公共节点一定是地址相同的两个节点,并不是值域相同的两个节点,如下图所示:

2.png

可以看到这两个链表的第一个公共节点是值域为44的这个节点,因为从这个节点往后的每一个节点的地址都是相同的

知道了什么是链表的第一个公共节点后,下面我们来看如何通过代码寻找这个节点:

(1):既然是两个链表寻找第一个公共节点,那么就肯定需要遍历我们的两个链表,设置两个指针cur,cur1分别指向我们的链表的头节点,用于我们链表的遍历。

(2):现在开始寻找我们的公共节点,cur和cur1分别开始从链表的头节点开始遍历,在遍历前我们还需要考虑一个问题,就是在找到我们链表的第一个公共节点前,我们在遍历节点的时候会发现链表的长度不同,遍历的节点的个数会不相同,这是需要进行一些操作,我们先来拿一个图进行举例:

2.png

可以看到在找到值域为44的这第一个公共节点前,我们的cur指针需要遍历三个节点才能找到,cur1指针需要遍历四个节点才可以找到,当cur和cur1同时遍历的时候,是永远不可能出现cur所指向的节点地址与cur1所指向的节点地址相同的情况的,所以在两个链表节点长度不相同的情况下,假设一个链表长度为lenA,一个链表长度为lenB,当lenA>lenB的时候,相当于第一个链表比第二个链表的长度要长,指向第一个链表的头节点的cur变量就需要先走lenA-lenB步,当lenA<lenB的时候,相当于第二个链表比第一个链表的长度要长,指向第二个链表的头节点的cur1变量就需要先走lenB-lenA步.较长的先走是为了确保两个链表能同时找到第一个公共节点,如果较长的链表中的遍历指针不先走那些差的步数,那么当同时向后遍历两个链表的时候是永远都找不到公共节点的.

(3):上述步骤完成后,当链表中含有公共节点的时候,我们的cur和cur1指针开始向后遍历,当找到链表的第一个公共节点后,返回cur即可,找不到返回null.

注意:我们的两个链表找到第一个公共节点前,它们的遍历指针cur和cur1一定是走了相同步数才找见的,如果判断出此时不能走相同步数,那么就必须使两个指针走相同的步数才可以,就需要我们使用(2)中的方法来实现.


代码示例

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        int length=0;
        int length1=0;
        ListNode cur=headA;
        ListNode cur1=headB;
        if(headA==null||headB==null){
            return null;
        }
        while(cur!=null){
            cur=cur.next;
            length++;
        }
        while(cur1!=null){
            cur1=cur1.next;
            length1++;
        }
        //这个地方一定要指回来
        cur=headA;
        cur1=headB;
        //为了让两个指针能走相同步数找到公共节点
        while(length>length1){
            cur=cur.next;
            length1++;
        }
        while(length<length1){
            cur1=cur1.next;
            length++;
        }
        //开始寻找公共节点
        while(cur!=cur1){
            cur=cur.next;
            cur1=cur1.next;
        }
        //返回第一个公共节点
        return cur;
    }
}

总结

1:此算法时间复杂度O(N),空间复杂度O(1)

2:此算法的思路比较巧妙,需要大家细细斟酌.


相关文章
|
7月前
|
存储 Python
链表中插入节点
链表中插入节点
|
2月前
LeetCode第二十四题(两两交换链表中的节点)
这篇文章介绍了LeetCode第24题的解法,即如何通过使用三个指针(preNode, curNode, curNextNode)来两两交换链表中的节点,并提供了详细的代码实现。
22 0
LeetCode第二十四题(两两交换链表中的节点)
|
2月前
Leetcode第十九题(删除链表的倒数第N个节点)
LeetCode第19题要求删除链表的倒数第N个节点,可以通过快慢指针法在一次遍历中实现。
44 0
Leetcode第十九题(删除链表的倒数第N个节点)
05_删除链表的倒数第N个节点
05_删除链表的倒数第N个节点
|
2月前
(剑指offer)18、删除链表的节点—22、链表中倒数第K个节点—25、合并两个排序的链表—52、两个链表的第一个公共节点(2021.12.07)
(剑指offer)18、删除链表的节点—22、链表中倒数第K个节点—25、合并两个排序的链表—52、两个链表的第一个公共节点(2021.12.07)
52 0
|
4月前
|
算法
LeetCode第24题两两交换链表中的节点
这篇文章介绍了LeetCode第24题"两两交换链表中的节点"的解题方法,通过使用虚拟节点和前驱节点技巧,实现了链表中相邻节点的交换。
LeetCode第24题两两交换链表中的节点
04_两两交换链表中的节点
04_两两交换链表中的节点
|
4月前
|
Python
【Leetcode刷题Python】剑指 Offer 22. 链表中倒数第k个节点
Leetcode题目"剑指 Offer 22. 链表中倒数第k个节点"的Python解决方案,使用双指针法找到并返回链表中倒数第k个节点。
54 5
|
4月前
|
Python
【Leetcode刷题Python】剑指 Offer 18. 删除链表的节点
Leetcode题目"剑指 Offer 18. 删除链表的节点"的Python解决方案,通过使用双指针法找到并删除链表中值为特定数值的节点,然后返回更新后的链表头节点。
45 4
|
5月前
|
安全 云计算
云计算自旋锁问题之在线程安全地删除链表节点时,需要频繁加锁会影响性能如何解决
云计算自旋锁问题之在线程安全地删除链表节点时,需要频繁加锁会影响性能如何解决
53 2