环形链表Ⅰ,Ⅱ三种解决方法(Python实现)

环形链表Ⅰ只是判断给定的链表中是否存在环形链表,存在则返回True,不存在则返回False
环形链表Ⅱ则是要返回链表开始入环的第一个节点。
在这里插入图片描述

一、快慢指针

  • 双指针第一次相遇:设两指针fast,slow指向链表头部,fast每轮走2步,slow每轮走1步,如果fast指针走过链表末端,说明链表无环 if not fast or not fast.next :return None
  • 当fast==slow时,两个指针在环中第一次相遇,分析fast和slow的步数关系,设链表共有a+b个节点,其中链表头部到链表入口有a个节点(不计链表入口节点)链表环有b个节点,设两指针分别走了f和s步,则有:f=2s(fast走的步数是slow步数的2倍),f=s+nb(fast比slow多走了n个环的长度),得到表达式,f=2nb,s=nb,即fast和slow指针分别走了2n和n个环的周长
  • 如果让指针从链表头部一直向前走,并统计步数k,那么所有走到链表入口节点数时的步数是:k=a+nb,而第一次双指针相遇时,slow指针才走了nb步,因此我们需要像一个办法让slow再走a步停下来,就可以到环的入口,这个方法依然使用双指针,slow位置不变,fast重新指向链表头部节点,slow和fast同时每轮向前一步,即此时f=0,s=nb,当fast指针走到f=a时,slow走到s=a+nb,此时两指针重合,并同时指向链表环的入口,返回slow指向的节点
class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        # 快慢指针
        fast,slow = head,head
        while True:
            # 如果fast直接走到链表末端,说明不存在环形链表,则返回None
            # if not fast:防止输入为:[] , if not fast.next: 因为fast指针要每次走两步,要确保走一步,因为fast.next.next可以是None
            if not fast or not fast.next:
                return None
            # 在设计第一次相遇的时候,fast走两步,slow走一步
            fast,slow = fast.next.next,slow.next
            # 如果第一次相遇,则跳出循环,构建第二次相遇,此时f=2nb,s=nb
            if fast==slow:
                break
        # slow还需要走a步,才能到达环形链表头节点
        fast = head
        while fast!=slow:
            fast,slow = fast.next,slow.next
        return fast

二、集合做法

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        # 集合做法
        exist = set()
        # 如果node不为空
        while head:
            print(head.val)
            # 如果此时的node在集合里
            if head in exist:
                return head
            # 如果node不在集合里
            exist.add(head)
            head = head.next
        return None

三、字典做法

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        # 字典做法    
        dic = {}
        while head:
            # dict.get() 
            # 返回指定键的值,get(键)
            if dic.get(head):
                # 如果该点之前被访问过,直接返回该点位置
                return head
            # 创建键值
            dic[head]=1
            head = head.next
        return None
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值