wayne
wayne
发布于 2025-08-24 / 1 阅读
0
0

LeetCode - 相交链表 / 无重复字符的最长子串

相交链表

给你两个单链表的头节点 headAheadB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null

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

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

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

自定义评测:

评测系统 的输入如下(你设计的程序 不适用 此输入):

  • intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0

  • listA - 第一个链表

  • listB - 第二个链表

  • skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数

  • skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数

评测系统将根据这些输入创建链式数据结构,并将两个头节点 headAheadB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案

 

示例 1:

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
— 请注意相交节点的值不为 1,因为在链表 A 和链表 B 之中值为 1 的节点 (A 中第二个节点和 B 中第三个节点) 是不同的节点。换句话说,它们在内存中指向两个不同的位置,而链表 A 和链表 B 中值为 8 的节点 (A 中第三个节点,B 中第四个节点) 在内存中指向相同的位置。

 

示例 2:

输入:intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at '2'
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [1,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
输出:No intersection
解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。
由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
这两个链表不相交,因此返回 null 。

 

提示:

  • listA 中节点数目为 m

  • listB 中节点数目为 n

  • 1 <= m, n <= 3 * 104

  • 1 <= Node.val <= 105

  • 0 <= skipA <= m

  • 0 <= skipB <= n

  • 如果 listAlistB 没有交点,intersectVal0

  • 如果 listAlistB 有交点,intersectVal == listA[skipA] == listB[skipB]

解题思路

这段代码用于查找两个单链表的交点(intersection node)。其核心逻辑是使用两个指针 ab 分别遍历链表 headAheadB,通过让指针在到达链表末尾时切换到另一个链表的头部,从而消除两个链表的长度差。如果两个链表相交,指针最终会相遇;否则,指针会同时变为 null,返回 null

代码逻辑步骤

  1. 初始检查:如果 headAheadBnull,直接返回 null(因为无交点)。

  2. 初始化指针a 指向 headAb 指向 headB

  3. 循环遍历

    • 循环条件:a != null || b != null(只要其中一个指针不为 null,就继续循环)。

    • 在循环内:

      • 首先检查 ab 是否指向同一个节点(即 a == b)。如果是,返回该节点(交点)。

      • 然后移动指针 a:如果 a 不为 null,则 a 指向 a.next;否则,a 指向 headB(切换到链表B的头部)。

      • 类似地移动指针 b:如果 b 不为 null,则 b 指向 b.next;否则,b 指向 headA(切换到链表A的头部)。

  4. 循环结束:如果循环退出(即两个指针都变为 null),说明没有交点,返回 null

为什么这样工作?

  • 如果两个链表相交,指针 ab 在遍历过程中会同时到达交点(因为切换链表后,路径长度相同)。

  • 如果不想交,指针最终会同时变为 null(即都遍历了两个链表的全部节点),循环退出。

示例模拟

假设链表A: 1->2->3->null,链表B: 4->5->null,无交点。

  • 指针 ab 的遍历路径:

    • a: 1 → 2 → 3 → null → 切换为 headB (4) → 5 → null

    • b: 4 → 5 → null → 切换为 headA (1) → 2 → 3 → null

  • ab 都变为 null 时,循环退出,返回 null

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA == null || headB == null){
            return null;
        }
        ListNode a = headA;
        ListNode b = headB;
        while(a != null || b != null){
            if(a==b){
                return a;
            }
            
            if(a!=null){
                a = a.next;
            }else{
                a = headB;
            }
            if(b!=null){
                b = b.next;
            }else{
                b = headA;
            }
            
        }
        return null;
    }
}

无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。

 

示例 1:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

 

提示:

  • 0 <= s.length <= 5 * 104

  • s 由英文字母、数字、符号和空格组成

解题思路(滑动窗口

代码实现了使用滑动窗口(双指针)和哈希集合来寻找最长无重复字符子串的长度。

让我们逐步梳理逻辑:

  1. 初始化:使用 set 来记录当前窗口中的字符,leftright 指针表示窗口的左右边界,maxSize 记录最大长度。

  2. 扩张窗口(右指针移动):如果当前字符不在 set 中,将其加入 set,更新 maxSize,然后 right++

  3. 收缩窗口(左指针移动):如果当前字符在 set 中(重复),则不断移动 left 指针,并移除 left 对应的字符,直到重复字符被移除(即窗口不再包含当前 right 字符)。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        HashSet<Character> set = new HashSet();
        int maxSize = 0;
        int left = 0;
        int right = 0;
        char[] ss = s.toCharArray();

        while(right < ss.length){
            if(!set.contains(ss[right])){
                set.add(ss[right]);
                maxSize = Math.max(maxSize,right - left +1);
                right++;
            }else{
                while(set.contains(ss[right])){
                    set.remove(ss[left]);
                    left++;
                }
            }
        }
        return maxSize;
   
    }
}


评论