数据结构与算法-链表(九):剑指offer-链表中环的入口节点(快慢指针的应用)

链表中环的入口节点

题目

给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。

解析

在这里插入图片描述

  • 如何判断里面是否有环
    利用快慢指针,快指针每次走两步,慢指针每次走一步,如果有环的话,那么当快慢指针在环中循环时,肯定有相遇的一天;如果没有环,那么快指针会先走到None。
    第一步,先判断有没有环
    第二步,找入口点
    那如何找入口点呢?fast走的步数与slow走的步数是相等的,只不过长度不等。
    假设slow走了 l l l的长度,那么fast就走了 2 l 2l 2l
    在这里插入图片描述
    x x x为从起点到环入口点的距离, a a a为从入口点到相遇点的距离,即蓝色长度; c c c为环的长度。
    slow走的长度 l = x + m c + a l=x+mc+a l=x+mc+a,其中 m m m是slow走的圈数;
    fast走的长度 2 l = x + n c + a 2l=x+nc+a 2l=x+nc+a,其中 n n n是fast走的圈数;
    那么有: 2 x + 2 m c + 2 a = x + n c + a = = > 2x+2mc+2a=x+nc+a==> 2x+2mc+2a=x+nc+a==>, x + ( 2 m − n ) c + a = 0 x+(2m-n)c+a=0 x+(2mn)c+a=0
    所以有: x = ( n − 2 m ) c − a = ( n − 2 m − 1 ) c + c − a x=(n-2m)c-a=(n-2m-1)c+c-a x=(n2m)ca=(n2m1)c+ca
    即起始点到环入口的距离x等于数个环的长度再加上从相遇点到起始点的长度。

于是,思路就来了,再设计两个速度一样的指针,一个指针从原点开始走,另一个指针从相遇点开始走,当从原点走的指针走到入口点的时候,另一个指针一定也到达了入口点(可能走了几圈环的距离+c-a).

算法步骤:

  • 边界条件:PHead=none
  • 判断是否有环:while 快指针和快指针的next存在的话就进入循环,直到两个两个相遇再结束;如果不存在就跳出了循环,然后判断快指针或者快指针的next是不是为空,如果为空就返回none
  • 找到入口节点
# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def EntryNodeOfLoop(self, pHead):
        # write code here
        
        if pHead == None:
            return None
        
        fastPointer = pHead
        slowPointer = pHead
        
        while fastPointer and fastPointer.next:
            fastPointer = fastPointer.next.next
            slowPointer = slowPointer.next
            if fastPointer == slowPointer:
                break
                
        if fastPointer == None or fastPointer.next == None:
            return None
            
        # 找入口,初始化fastpointer,改变其性质与slow一样
        fastPointer = pHead
        while fastPointer != slowPointer:
            fastPointer = fastPointer.next
            slowPointer = slowPointer.next
        return fastPointer
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值