zoukankan      html  css  js  c++  java
  • 【LeetCode题解】142_环形链表2(Linked-List-Cycle-II)

    描述

    给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

    说明:不允许修改给定的链表。

    进阶
    你是否可以不用额外空间解决此题?

    解法一:哈希表

    思路

    最直接的解法就是利用一个集合保存每次遍历的节点的引用。之后,从链表头开始遍历,每遍历一个节点,就判断该节点的引用是否在集合中,如果不在集合中,则将该节点的引用放入集合中;如果在集合中,则返回该节点的引用(环的入口)。当然,如果能遍历到链表尾部,此时链表无环,返回 null

    Java 实现

    /**
     * Definition for singly-linked list.
     * class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) {
     *         val = x;
     *         next = null;
     *     }
     * }
     */
    
    import java.util.Set;
    import java.util.HashSet;
    
    public class Solution {
        public ListNode detectCycle(ListNode head) {
            ListNode curr = head;
            Set<ListNode> nodesSeen = new HashSet<>();
            while (curr != null) {
                if (nodesSeen.contains(curr)) {
                    return curr;
                }
                nodesSeen.add(curr);
                curr = curr.next;
            }
            return curr;
        }
    }
    

    Python 实现

    # Definition for singly-linked list.
    # class ListNode(object):
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution(object):
        def detectCycle(self, head):
            """
            :type head: ListNode
            :rtype: ListNode
            """
            curr = head
            nodes_seen = set()
            while curr:
                if curr in nodes_seen:
                    return curr
                nodes_seen.add(curr)
                curr = curr.next
            return curr
    

    复杂度分析

    • 时间复杂度:(O(n))
    • 空间复杂度:(O(n))

    解法二:双指针

    思路

    LeetCode 第 141 题一样,如果不想占用额外的空间的话,可以采用双指针的方式。

    假设链表的起始节点为 A,环的入口节点为 B,两个指针(快慢指针)相交节点为 C,AB 两点之间的长度为 (x),BC 两点之间的长度为 (y),CB 两点之间的长度为 (z)。慢指针 slow 走过的长度为 (x+y),快指针 fast 为了“赶上”慢指针,应该走过的长度为 (x + y + z + y),同时,由于快指针的速度是慢指针的两倍,因此相同时间内,快指针走过的路程应该是慢指针(走过的路程)的两倍,即

    [x + y + z + y = 2 (x + y) ]

    化简得,

    [x = z ]

    因此,如果此时有另外一个慢指针 slow2 从起始节点 A 出发,则两个慢指针会在节点 B (环的入口)相遇。

    Java 实现

    /**
     * Definition for singly-linked list.
     * class ListNode {
     *     int val;
     *     ListNode next;
     *     ListNode(int x) {
     *         val = x;
     *         next = null;
     *     }
     * }
     */
    
    public class Solution {
        public ListNode detectCycle(ListNode head) {
            ListNode slow = head, fast = head;
            while (fast != null && fast.next != null) {
                slow = slow.next;
                fast = fast.next.next;
                
                if (slow == fast) {
                    ListNode slow2 = head;
                    while (slow != slow2) {
                        slow = slow.next;
                        slow2 = slow2.next;
                    }
                    return slow;
                }
            }
            return null;
        }
    }
    // Runtime: 1 ms
    // Your runtime beats 100.00 % of python submissions.
    

    Python 实现

    # Definition for singly-linked list.
    # class ListNode(object):
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution(object):
        def detectCycle(self, head):
            """
            :type head: ListNode
            :rtype: ListNode
            """
            slow, fast = head, head
            while fast and fast.next:
                slow = slow.next
                fast = fast.next.next
                
                if slow == fast:
                    slow2 = head
                    while slow != slow2:
                        slow = slow.next
                        slow2 = slow2.next
                    return slow
            return None
    # Runtime: 44 ms
    # Your runtime beats 99.73 % of python submissions.
    

    复杂度分析

    • 时间复杂度:(O(n)),其中 (n) 表示链表的长度。最坏的情况下(链表有环),需要迭代的次数为 (x + y + z = n) 次,因此时间复杂度为 (O(n))
    • 空间复杂度:(O(1)),只需要存储 3 个引用
  • 相关阅读:
    ffmpeg rtmp推流 视频转码
    java日志发展史 log4j slf4j log4j2 jul jcl 日志和各种桥接包的关系
    nginx stream 流转发,可以转发rtmp、mysql访问流,转发rtmp、jdbc请求
    java web http 转https 通过nginx代理访问
    linux 服务器磁盘挂载
    novnc 通过websockify代理 配置多点访问
    linux 文件服务 minio 安装部署配置
    AOP实现原理,手写aop
    java 泛型
    JAVA反射getGenericSuperclass()用法
  • 原文地址:https://www.cnblogs.com/xugenpeng/p/9912496.html
Copyright © 2011-2022 走看看