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

链表中环的入口节点

题目

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

解析

在这里插入图片描述

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

于是,思路就来了,再设计两个速度一样的指针,一个指针从原点开始走,另一个指针从相遇点开始走,当从原点走的指针走到入口点的时候,另一个指针一定也到达了入口点(可能走了几圈环的距离+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
发布了49 篇原创文章 · 获赞 2 · 访问量 1821

猜你喜欢

转载自blog.csdn.net/liuluTL/article/details/105016339