「日更刷题」面试题 02.07. 链表相交

简介: 「日更刷题」面试题 02.07. 链表相交

一、前言

每日算法坚持第四天,该专栏争取日日更新,加油

二、简介和示例

简介

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

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

网络异常,图片无法展示
|

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

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

链表数据结构

public class ListNode {
    public int val;
    public ListNode next;
    public ListNode() {
    }
    public ListNode(int val) {
        this.val = val;
    }
    public ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
}
复制代码

示例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]

三、解题

错误示范

注意: 这里求的是指针相同的情况下的交点, 而不是求相同的数值, 这个就很烦, 最开始读题没有读明白, 提交代码的时候还报错

网络异常,图片无法展示
|

错误代码展示

public static ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    // 两个链表, 记录 headA和 headB的元素值
    List<Integer> list1 = new ArrayList<>();
    List<Integer> list2 = new ArrayList<>();
    // 链表A和B, 题中有说不改变原先的链表
    ListNode one = headA;
    ListNode two = headB;
    // 遍历获取链表的值
    while(one != null){
        list1.add(one.val);
        one = one.next;
    }
    while(two != null){
        list2.add(two.val);
        two = two.next;
    }
    // 判断最短长度去循环
    int size = list1.size() < list2.size() ? list1.size() : list2.size();
    // 返回值链表
    ListNode node = null;
    // 遍历循环
    int j = 1;
    for (int i = size - 1 ; i >= 0; i--) {
        if (list1.get(i) != list2.get(list2.size() - j)){
            if (i < size){
                node = new ListNode(list1.get(i + 1));
            }
            break;
        }
        j++;
    }
    return node;
}
复制代码

思路分析

  • 首先一定要注意, 我们要求的是同指针下的交点
  • 因为题中要求不改变原链表结构
  • 首先, 我们先搞两个链表去接受 headA和 headB
  • 其次我们就要把我们的链表长度保持一致
  • 首先计算出 headA 和 headB的长度
  • 然后将长的那个链表移动到和短的链表保持一致的长度
  • 最后去循环遍历判断两个链表是否有一致的值. 如果有则返回

注意:

第一次记录链表长度的循环结束之后要记得重新为链表赋值

比较的是指针是否相同, 最后一个循环比较的是 nodeA == nodeB. 而不是 nodeA.val == nodeB.val

四、代码展示

public static ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        // 两个链表, 接受 headA和 headB
        ListNode nodeA = headA;
        ListNode nodeB = headB;
        // 记录两个链表的长度
        Integer skipA = 0, skipB = 0;
        // 计算出两个链表的长度
        while(nodeA != null){
            skipA++;
            nodeA = nodeA.next;
        }
        while(nodeB != null){
            skipB++;
            nodeB = nodeB.next;
        }
        // 循环结束之后要重新为两个链表赋值
        nodeA = headA;
        nodeB = headB;
        // 两个链表长度差
        Integer n = skipA - skipB;
        // 让链表A为最长链表, 方便我们后续移动链表操作
        if (skipA < skipB){
            // 交换链表节点
            ListNode node = nodeA;
            nodeA = nodeB;
            nodeB = node;
            // 如果B链表长. 那么长度差是负值, 所以这里要重新进行计算
            n = skipB - skipA;
        }
        // n是长度差, 缩短链表A至长度与B相等
        while(n-- > 0 ){
            nodeA = nodeA.next;
        }
        // 记录返回值
        ListNode node = null;
        // 循环判断链表值是否相等
        while(nodeA != null){
            // 如果两个值相等, 则跳出循环
            if (nodeA == nodeB){
                return nodeA;
            }
            nodeA = nodeA.next;
            nodeB = nodeB.next;
        }
        return null;
    }
复制代码

五、提交代码

网络异常,图片无法展示
|

注: 刷 LeetCode感觉自己做对了, 但是测试是错的时候, 一定要看评论区, 肯定是有哪里自己没有考虑到



目录
相关文章
|
1天前
|
算法
LeetCode刷题---21.合并两个有序链表(双指针)
LeetCode刷题---21.合并两个有序链表(双指针)
|
1天前
|
算法 测试技术
LeetCode刷题--- 430. 扁平化多级双向链表(深度优先搜索)
LeetCode刷题--- 430. 扁平化多级双向链表(深度优先搜索)
|
1天前
|
存储
实现单链表的基本操作(力扣、牛客刷题的基础&笔试题常客)
实现单链表的基本操作(力扣、牛客刷题的基础&笔试题常客)
145 38
|
1天前
|
算法
【刷题】 leetcode 面试题 08.05.递归乘法
递归算法是一种在计算机科学和数学中广泛应用的解决问题的方法,其基本思想是利用问题的自我相似性,即将一个大问题分解为一个或多个相同或相似的小问题来解决。递归算法的核心在于函数(或过程)能够直接或间接地调用自身来求解问题的不同部分,直到达到基本情况(也称为基础案例或终止条件),这时可以直接得出答案而不必再进行递归调用。
25 4
【刷题】 leetcode 面试题 08.05.递归乘法
|
1天前
|
存储 算法 安全
【刷题】 leetcode 面试题 01.06 字符串压缩
来看效果: 非常好!!!过啦!!!
25 5
【刷题】 leetcode 面试题 01.06 字符串压缩
|
1天前
|
存储 Java 编译器
链表面试题的总结和思路分享
链表面试题的总结和思路分享
|
1天前
|
C语言 C++ 索引
【力扣】141. 环形链表、160. 相交链表、206.反转链表、234. 回文链表
【力扣】141. 环形链表、160. 相交链表、206.反转链表、234. 回文链表
|
1天前
|
算法
算法系列--链表刷题(二)(下)
算法系列--链表刷题(二)(下)
18 0
|
1天前
数据结构--链表刷题(一)快慢指针(上)
数据结构--链表刷题(一)快慢指针
16 0
|
1天前
|
机器学习/深度学习 人工智能 算法
LeetCode刷题--- 面试题 01.07. 旋转矩阵(原地旋转+翻转替旋转)
LeetCode刷题--- 面试题 01.07. 旋转矩阵(原地旋转+翻转替旋转)