首页 > 编程语言 >[Leetcode]经典算法

[Leetcode]经典算法

时间:2024-07-07 15:08:29浏览次数:15  
标签:head slow fast next 链表 算法 经典 Leetcode 指针

检测环

快慢指针法是一种用于检测链表中是否存在环的有效方法,同时也可以找到环的起点。该方法的原理基于两个指针在链表上同时移动,其中一个移动得更快,而另一个移动得更慢。

  1. 检测环的存在:

    • 使用两个指针,一个称为快指针(fast),一个称为慢指针(slow)。
    • 在每一步中,快指针向前移动两步,而慢指针只移动一步。
    • 如果链表中不存在环,那么快指针最终会到达链表的尾部,此时可以确定链表中无环。
    • 如果链表中存在环,由于快指针的速度比慢指针快,它们最终会相遇。
  2. 找到环的起点:

    • 一旦快慢指针相遇,说明链表中存在环。
    • 将其中一个指针(例如慢指针)重新移到链表的头部,保持另一个指针在相遇点。
    • 然后,两个指针以相同的速度前进,直到它们再次相遇。这次相遇点就是环的起点。

为什么这个方法有效?

  • 如果链表中不存在环,快指针将最终到达链表的尾部,而慢指针也会到达链表的末尾。由于没有环,两者不会相遇。
  • 如果链表中存在环,快慢指针最终会在环中的某一点相遇。此时,将其中一个指针移到链表头部,它们再次相遇的地方就是环的起点。

这个方法的时间复杂度为O(N),其中N是链表的长度。因为快指针每次移动两步,而慢指针每次移动一步,所以快指针最多需要N/2步就能遇到慢指针。在找到相遇点后,重新移动指针的过程最多需要再走N步。

证明

让我们来证明一下,为什么上面两个说法是正确的。

首先,进入环之前的路越长,快慢指针之间的差距就越大,如果这段路足够长,甚至会出现快指针已经在环里面走了好几圈,但是慢指针还没有进入环的情况。

但是不管前面的路有多长,不管慢指针进入环的时候,快指针在环的哪个位置,慢指针进入环以后,快指针总是可以在慢指针走不到一圈的时候追上他,因为慢指针在环内走了一圈的时候,快指针已经走了两圈,一定可以追得上。

image

下面我们来列算式

进入环之前的路长度为:P

慢节点在环内走过的路为:S

环的总长度为:C

慢指针总共走过的长度:P+S

那么快指针走过的总长度:2(P+S)

快指针在环内走过的长度:P+2S

快慢指针相遇的时候,他们处在同一个位置上:S%C = (P+2S)%C

化简,(P+S)%C = 0,也就是说(P+S) = NC

现在我们在位置S上,再走P的长度就可以回到环的起点。

先来看如何判断是否有环

Leetcode 141. 环形链表

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def hasCycle(self, head: Optional[ListNode]) -> bool:
        if not head:
            return False
        fast = head
        slow = head
        while fast.next and fast.next.next:
            fast = fast.next.next
            slow = slow.next
            if fast == slow:
                return True
        return False

再来看环的起点在哪里

LCR 022. 环形链表 II

给定一个链表,返回链表开始入环的第一个节点。 从链表的头节点开始沿着 next 指针进入环的第一个节点为环的入口节点。如果链表无环,则返回 null。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意,pos 仅仅是用于标识环的情况,并不会作为参数传递到函数中。

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

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def detectCycle(self, head: ListNode) -> ListNode:
        if not head:
            return False

        fast = head
        slow = head

        while fast.next and fast.next.next:
            fast = fast.next.next
            slow = slow.next

            if fast == slow:
                fast = head
                while fast != slow:
                    fast = fast.next
                    slow = slow.next  
                return fast
        return False

标签:head,slow,fast,next,链表,算法,经典,Leetcode,指针
From: https://www.cnblogs.com/DCFV/p/18288530

相关文章

  • leetcode678:有效的括号字符串
    给你一个只包含三种字符的字符串,支持的字符类型分别是 '('、')' 和 '*'。请你检验这个字符串是否为有效字符串,如果是 有效 字符串返回 true 。有效 字符串符合如下规则:任何左括号 '(' 必须有相应的右括号 ')'。任何右括号 ')' 必须有相应的左括号 '(' 。左括......
  • 【LeetCode 0024】【链表】交换单链表相邻两个节点
    SwapNodesinPairsGivena linkedlist,swapeverytwoadjacentnodesandreturnitshead.Youmustsolvetheproblemwithout modifyingthevaluesinthelist’snodes(i.e.,onlynodesthemselvesmaybechanged.)Example1:**Input:**head=[1,2,3......
  • 【LeetCode 0141】【链表】【双指针之快慢指针】判断给定单链表是否存在环
    LinkedListCycleGivenhead,theheadofalinkedlist,determineifthelinkedlisthasacycleinit.Thereisacycleinalinkedlistifthereissomenodeinthelistthatcanbereachedagainbycontinuouslyfollowingthe next pointer.Internal......
  • DAY 1 数据结构与算法 (选择排序,冒泡排序,插入排序)
    1.选择排序        选择排序(SelectionSort)是一种简单直观的排序算法。其基本思想是每一次从待排序的数据元素中选择最小(或最大)的一个元素,放在已排好序的元素序列的末尾,直到全部待排序的数据元素排好序为止。即每一次设定一个数为最大或者最小值,然后与其他的数进行交......
  • 动态规划算法-以中学排班管理系统为例
    1.动态规划算法介绍 1.算法思路动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问......
  • 数据结构题目:模式匹配的BF算法
    1、实验目的键盘输入目标串(主串)s、模式串(子串)t,编写程序,实现顺序串的BF模式匹配算法。2、实验具体要求匹配成功,输出位序,匹配不成功,显示相应提示信息。例如:s=“aababcdcccc”,t=“bcd”。3、实验设计思路(编程语言、模块划分及函数功能描述等)模块划分及函数功能描述:(1)主程序......
  • 「代码随想录算法训练营」第一天(补) | 数组 part1
    704.二分查找题目链接:https://leetcode.cn/problems/binary-search/题目难度:简单文章讲解:https://programmercarl.com/0704.二分查找.html视频讲解:https://www.bilibili.com/video/BV1fA4y1o715题目状态:通过个人思路:就是简单的二分查找思路,判断数组中间的值是否等于目......
  • 算法金 | 一个强大的算法模型,GPR !!
    大侠幸会,在下全网同名「算法金」0基础转AI上岸,多个算法赛Top「日更万日,让更多人享受智能乐趣」抱个拳,送个礼高斯过程回归(GPR)是一种非参数化的贝叶斯方法,用于解决回归问题。与传统的线性回归模型不同,GPR能够通过指定的核函数捕捉复杂的非线性关系,并提供不确定性的估计......
  • [LeetCode] 1366. Rank Teams by Votes 通过投票对团队排名
    Inaspecialrankingsystem,eachvotergivesarankfromhighesttolowesttoallteamsparticipatinginthecompetition.Theorderingofteamsisdecidedbywhoreceivedthemostposition-onevotes.Iftwoormoreteamstieinthefirstposition,wecon......
  • 「杂文」算法竞赛之黑话大赏
    写在前面欢迎投稿。罚时一种根据选手完成题目的耗时,用于对通过题目数量相同的选手,进行排名的指标。仅有选手成功通过的题目,才会计算罚时。一道成功通过的题目的罚时为:选手第一次通过该题目时间,距离比赛开始时间之差,再加上未成功提交的罚时惩罚。选手总罚时为:选手所有通过题......