首页 > 其他分享 >力扣面试题02.07.链表相交

力扣面试题02.07.链表相交

时间:2024-10-17 22:50:00浏览次数:8  
标签:力扣 面试题 ListNode currB 链表 currA null 节点

题目链接:面试题 02.07. 链表相交 - 力扣(LeetCode)

给你两个单链表的头节点 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]

解法一:哈希集合

思路:

遍历链表A,将链表A中的所有节点添加到HashSet集合中,然后遍历链表B,对于遍历到的每个节点,判断该节点是否在哈希集合中:

  • 如果当前节点不在哈希集合中,则继续遍历下一个节点;

  • 如果当前节点在哈希集合中,则后面的节点都在哈希集合中,返回该节点。

代码:

/**
 * 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) {
        Set<ListNode> m=new HashSet<ListNode>();
        ListNode currA=headA;
        ListNode currB=headB;
        while(currA!=null){
            m.add(currA);
            currA=currA.next;
        }
        while(currB!=null){
            if(m.contains(currB)){
                return currB;
            }else{
                currB=currB.next;
            }
        }
        return null;
    }
}

复杂度分析:

时间复杂度:O(n + m)         遍历两条链表

空间复杂度:O(m)         哈希集合

解法二:同步移动

思路:

1.求出两个链表的长度,计算出两个链表长度的差值,移动currA或currB使两者同步。

2.此时我们就可以比较currA和currB是否相同,如果不相同,同时向后移动currA和currB,如果遇到currA == currB,则找到交点并返回该节点。

否则返回空指针。

代码:

/**
 * 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 currA=headA;
        ListNode currB=headB;
        int numA=0,numB=0;
        //注意交点不是数值相等,而是指针相等
        while(currA!=null){
            numA++;//链表A的长度
            currA=currA.next;
        }
        while(currB!=null){
            numB++;//链表B的长度
            currB=currB.next;
        }
        currA=headA;
        currB=headB;
        
        int t=0;
        if(numA>numB){
            t=numA-numB;
            while(t!=0){
                currA=currA.next;//currA先走,直到和B同步
                t--;
            }
            //此时currA和currB同步
            while(currA!=null&&currB!=null){
                if(currA==currB){
                    return currA;
                }else{
                    currA=currA.next;
                    currB=currB.next;
                }
            }
        }else{
            t=numB-numA;
            while(t!=0){
                currB=currB.next;//currB先走,直到和A同步
                t--;
            }
            //此时currA和currB同步
            while(currA!=null&&currB!=null){
                if(currA==currB){
                    return currA;
                }else{
                    currA=currA.next;
                    currB=currB.next;
                }
            }
        }
        return null;
    }
}

复杂度分析: 

时间复杂度: O(m+n)        遍历链表A:O(m),遍历链表B:O(n)同步指针:O(t)

空间复杂度:O(1)

解法三:双指针

思路:

使用双指针实现同步遍历

  • p1遍历完链表A(p1==null)后,让它开始遍历链表B
  • p2遍历完链表B(p2==null)后,让它开始遍历链表A

代码:

/**
 * 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) {
        if(headA==null || headB==null){
            return null;
        }
        ListNode p1=headA;
        ListNode p2=headB;
        while(p1!=p2){
            // p1 走一步,如果走到 A 链表末尾,转到 B 链表
            if(p1==null) p1=headB;
            else p1=p1.next;
            // p2 走一步,如果走到 B 链表末尾,转到 A 链表
            if(p2==null) p2=headA;
            else p2=p2.next;
        }
        return p1;
    }
}

复杂度分析:

时间复杂度:O(m + n)         遍历两条链表

空间复杂度:O(1)         

标签:力扣,面试题,ListNode,currB,链表,currA,null,节点
From: https://blog.csdn.net/m0_74931837/article/details/142862389

相关文章

  • 力扣142.环形链表II
    题目链接:142.环形链表II-力扣(LeetCode)给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。为了表示给定链表中的环,评测系统内部使用整数 pos 来表示......
  • 力扣242.有效的字母异位词
    题目链接:242.有效的字母异位词-力扣(LeetCode)给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的 字母异位词。示例 1:输入:s="anagram",t="nagaram"输出:true示例2:输入:s="rat",t="car"输出:false提示:1<=s.length,t.length<=......
  • 力扣349.两个数组的交集
    题目链接:349.两个数组的交集-力扣(LeetCode)给定两个数组 nums1 和 nums2 ,返回 它们的 交集。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。示例1:输入:nums1=[1,2,2,1],nums2=[2,2]输出:[2]示例2:输入:nums1=[4,9,5],nums2=[......
  • 【状态机DP】力扣309. 买卖股票的最佳时机含冷冻期
    给定一个整数数组prices,其中第prices[i]表示第i天的股票价格。​设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):卖出股票后,你无法在第二天买入股票(即冷冻期为1天)。注意:你不能同时参与多笔交易(你必须在再次购......
  • 【状态机DP】【hard】力扣188. 买卖股票的最佳时机 IV
    给你一个整数数组prices和一个整数k,其中prices[i]是某支给定的股票在第i天的价格。设计一个算法来计算你所能获取的最大利润。你最多可以完成k笔交易。也就是说,你最多可以买k次,卖k次。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。示例......
  • 【数据结构】之链表详解
    链表是一种常用的数据结构,它是一种线性数据结构,但与数组不同,它并非连续存储数据,而是通过指针将数据节点连接起来。每个节点都包含数据域和指向下一个节点的指针域。这种结构赋予链表独特的优势和局限性,使其在某些场景下优于数组,在另一些场景下则相对逊色。本文将深入探讨链表,包......
  • Java数据结构二叉树面试题精华(画图详解)
    前言:    针对二叉树,因为涉及到递归,需要跟多的练习强化递归的思想,其中也包括需要画图理解一些想不通的问题来提升自己!    一下面这些题为例,一起来提升自己的逻辑思维能力!(可能其中一些题已经写过,但是希望能再写一遍有助于提高代码能力)相同的树:      ......
  • 京东Android最全面试题及参考答案
    Android常用控件TextViewTextView是Android中最基础的文本显示控件,用于在界面上展示静态的文本信息。它可以设置文本的内容、字体大小、颜色、样式等属性。在应用中,常用于显示标题、说明文字、提示信息等。例如,在一个登录界面中,TextView可以用来显示“用户名”“密......
  • 翻转链表常用写法
    翻转链表常用写法循环写法classSolution{public:ListNode*reverseList(ListNode*head){ListNode*prev=nullptr,*next=nullptr,*now=head;while(now){next=now->next;now->next=prev;prev=......
  • Dubbo你掌握的如何?快看看这30道高频面试题!
    前言Dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。简单的说,dubbo就是个服务框架,如果没有分布式的需求,其实是不需要用的,只有在分布式的时候,才有dubbo这样的分布式服务框架的需求,并且本质上是个服务调用的东东,说白了就是个远程......