• 【leetcode】142.环形链表 II


    142.环形链表 II

    跟141.环形链表类似,都是用哈希表和快慢指针

    哈希表法

    复杂度分析

    • 时间复杂度:O(n)O(n)O(n)
    • 空间复杂度:O(n)O(n)O(n)
    class Solution(object):
        def detectCycle(self, head):
            visited = set() # 注意集合跟字典的区别
            while head is not None:
                if head in visited:
                    return head # 能够直接返回结点所在的下标
                else:
                    visited.add(head)
                    head = head.next
            return None
    

    基于快慢指针的floyd算法

    分为两个阶段

    • 阶段一

      跟141.环形链表类似,定义快慢指针遍历链表,如果链表没有环,那么快指针先遍历完此时可以返回NULL,如果有环那么一定会相遇,那么分析相遇的点。

    在这里插入图片描述

    环中的节点从 0 到 C-1编号,其中 C是环的长度,非环节点从 -F 到 -1编号,其中 F是环以外节点的数目。 F 次迭代以后,慢指针指向了 0 且快指针指向某个节点 h (此时快指针可能绕过几次环,即F=h(modC)F=h(mod C)F=h(modC),设此时到第一次相遇的时刻为t,那么有
    2t=t+C−h 2t=t+C-h 2t=t+Ch
    t=C−ht=C-ht=Ch,慢指针走过的环中距离为C−hC-hCh,也就是说第一次相遇时慢指针走了不到一圈,而快指针走了最少一圈。

    • 阶段二

    ​ 如上,相遇时慢指针走过了F+aF+aF+a距离(上文提到慢指针在第一次相遇时不会走到一圈),而快指针则走过了F+k(a+b)+a,k=1,2,3...F+k(a+b)+a,k=1,2,3...F+k(a+b)+ak=1,2,3...,此时有:
    2(F+a)=F+k(a+b)+a 2(F+a)=F+k(a+b)+a 2(F+a)=F+k(a+b)+a
    得出F=b+(k−1)CF=b+(k-1)CF=b+(k1)C,那么为了找到环开始的位置,可以建一个两个指针,一个指向链表的头,一个指向相遇的结点,一直遍历直到两者的值相等,说明到了环开始的位置

    复杂度分析

    • 时间复杂度:O(n)O(n)O(n)
    • 空间复杂度:O(1)O(1)O(1)
    class Solution(object):
        def getIntersect(self, head):
            '''检查链表是否存在环形以及返回相遇的结点
            '''
            slow = head
            fast = head
            while fast  and fast.next :
                slow =slow.next
                fast = fast.next.next
                if slow == fast:
                    return slow
            return None
    
        def detectCycle(self, head):
            if head is None:
                return None
            intersect = self.getIntersect(head)
            if intersect is None:
                return None
            # 阶段二
            ptr1 = head
            ptr2 = intersect
            while ptr1 != ptr2:
                ptr1 = ptr1.next
                ptr2 = ptr2.next
            return ptr1
    
  • 相关阅读:
    c# 查找进程
    第三方打包工具
    WebClient 上传和下载
    .net 读取文件
    winfrom 圆角panel
    窗体或控件的两种拖动方式
    winfrom 获取当前屏幕尺寸
    动态修改配置文件web服务地址
    将字符串编码成 GBK
    .net(C#) 读取配置文件
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13281632.html
Copyright © 2020-2023  润新知