LeetCode2.07链表相交

2.07链表相交

给你两个单链表的头节点 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 个节点。 示例 2:

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

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

提示:

listA 中节点数目为 m listB 中节点数目为 n 0 <= m, n <= 3 * 104 1 <= Node.val <=
105 0 <= skipA <= m 0 <= skipB <= n 如果 listA 和 listB 没有交点,intersectVal
为 0 如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] ==
listB[skipB + 1]


思路一

借鉴大神操作,追击相遇问题
太巧妙了

如果两个链表相交,两个指针最终会在相交节点相遇,因为它们遍历的总长度是相同的(先走完一个链表,再走另一个链表的剩余部分)。
如果两个链表不相交,两个指针最终会同时指向 null,这是因为它们走过的路径长度相同,但是都走完了两个链表,最后都指向了 null。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode A = headA;
        ListNode B = headB;

        //当A B不相遇时
        while(A != B){
            //A如果不为空,A向后走否则将A指向B链首
            A = A != null ? A.next : headB;
            //B如果不为空,B向后走,否则将B指向A的链首
            B = B != null ? B.next : headA;
        }
        //返回重合点
        return A;
    }
}

思路二

比较麻烦,但是更加容易想到哦

  1. 找出A ,B链表的长度差并将两条链表尾部对齐
  2. 假设A长B短,那么从B的开头,A的(lenA - lenB)位置开始遍历
  3. AB同时向后移动,直到AB找到相同的后缀
  4. 找不到就直接返回null
    如图对齐
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        //找出A ,B链表的长度差并将两条链表尾部对齐
        //假设A长B短,那么从B的开头开始遍历
        //AB同时向后移动,直到AB找到相同的后缀
        //找不到就直接返回null

        ListNode A = headA, B = headB;
        int lenA = 0 , lenB = 0;

        //寻找A的长度
        while(A != null){
            lenA ++;
            A = A.next;
        }

        //寻找B的长度
        while (B != null){
            lenB ++;
            B = B.next;
        }

        //重置A, B指针为初始位置
        A = headA;
        B = headB;

        //让A为最长链表的头,lenA为其长度
        if(lenB > lenA){

            //交换A ,B指针位置(交换三步走)
            ListNode tmpNode = A;
            A = B;
            B = tmpNode;

            //交换lenA ,lenB
            int tmp = lenA;
            lenA = lenB;
            lenB = tmp;
        }

        //求A B长度差
        int gap = lenA - lenB;

        //让A和B在同一起点上
        while (gap > 0){
            A = A.next;
            --gap;
        }

        //当A不为空时,遇到相同则返回
        while (A != null){
            if(A == B){
                return A;
            }
            A = A.next;
            B = B.next;
        }
        return null;

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值