链表相交面试题

本文介绍了如何在两个给定的单链表中找到它们的相交节点,方法一是通过计算链表长度并遍历找到相等步长的节点,方法二是通过交替遍历直到找到相同的节点。题目保证了链表无环且不包含0作为相交节点值。
摘要由CSDN通过智能技术生成

目录

题目

思路

方法一

方法二

代码


题目

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

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

题目数据 保证 整个链式结构中不存在环。

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

示例 1:

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

思路

方法一

就是求两个链表交点节点的指针。交点不是数值相等,而是指针相等。

他是链表尾部相交,所以我们需要先得到两个链表的长度。后面为了方便分析判断,链表长的我们让他都为A。

 到这里以后我们开始遍历A和B然后找到它的相同节点的头。

方法二

设「第一个公共节点」为 node ,「链表 headA」的节点数量为 a ,「链表 headB」的节点数量为 b ,「两链表的公共尾部」的节点数量为 c ,则有:

头节点 headA 到 node 前,共有 a−c 个节点;
头节点 headB 到 node 前,共有 b−c 个节点;

构建两个节点指针 A​ , B 分别指向两链表头节点 headA , headB ,做如下操作:

指针 A 先遍历完链表 headA ,再开始遍历链表 headB ,当走到 node 时,共走步数为:
a+(b−c)
指针 B 先遍历完链表 headB ,再开始遍历链表 headA ,当走到 node 时,共走步数为:
b+(a−c)
如下式所示,此时指针 A , B 重合,并有两种情况:

a+(b−c)=b+(a−c)
若两链表 有 公共尾部 (即 c>0 ) :指针 A , B 同时指向「第一个公共节点」node 。
若两链表 无 公共尾部 (即 c=0) :指针 A , B 同时指向 null 。
因此返回 A 即可。

. - 力扣(LeetCode)

如链表A+链表B=链表C1

链表B+链表A=链表C2

A -> a1 a2 c1 c2 c3

B -> b1 b2 b3 c1 c2 c3

C1 -> a1 a2 c1 c2 c3 b1 b2 b3 c1 c2 c3

C2 -> b1 b2 b3 c1 c2 c3 a1 a2 c1 c2 c3

此时C1和C2的长度一定相同。 而C1和C2的结尾就一定是相交的链表。

代码

public class Solution {//方法一
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode curA=headA;//分别定义两个链表的指针
        ListNode curB=headB;
        int lenA=0,lenB=0;//先暂定他俩的长度都为0,后面再进行判断计算
        while(curA!=null){//当指针不为null的时候一直移动指针,然后让长度++,可以计算出A的长度
            lenA++;
            curA=curA.next;
        }
        while(curB!=null){//计算链表B的长度
            lenB++;
            curB=curB.next;
        }
        curA=headA;//通过上面的操作curA或者B的值改变了,所以需要进行归位再进行下一步操作
        curB=headB;
        if(lenB>lenA){//为了方便让长一点的链表都为A,所以当B长的时候我们进行交换
            int lent=lenA;//先交换长度
            lenA=lenB;
            lenB=lent;
            ListNode curt=curA;//再交换指针
            curA=curB;
            curB=curt;
        }
        int gap=lenA-lenB;//这一步是进行上述图解的一步
        while(gap-->0){//移动A指针
            curA=curA.next;
        }
        while(curA!=null){//同时移动A和B
            if(curA==curB){//找到,返回值
                return curA;
            }
            curA=curA.next;
            curB=curB.next;
        }
        return null;//没找到,返回null
        
    }
}
public class Solution {//方法二
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode curA=headA;
        ListNode curB=headB;
       while(curA!=curB){//循环寻找
        if(curA==null) curA=headB;//找完A了,让他去找B
        else   curA=curA.next;//还没找完
        if(curB==null) curB=headA;//找完B了,让他去找A
        else    curB=curB.next;//还没找完
       }
       return curA;//返回找到的
    }
}

  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值