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

输入: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

附上牛客网链接

点击此处进入牛客网

思路与代码

====================================================================

思路展现

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

在这里插入图片描述

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

在这里插入图片描述

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

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

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

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

在这里插入图片描述

可以看到在找到值域为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(headAnull||headBnull){

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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值