当前位置:   article > 正文

LeetCode-287: Find the Duplicate Number(寻找重复数字——弗洛伊德循环寻找算法)_弗洛伊德循环查找算法

弗洛伊德循环查找算法

Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.

Example 1:

Input: [1,3,4,2,2]
Output: 2
  • 1
  • 2

Example 2:

Input: [3,1,3,4,2]
Output: 3
  • 1
  • 2

Note:

  1. You must not modify the array (assume the array is read only).
  2. You must use only constant, O(1) extra space.
  3. Your runtime complexity should be less than O(n2).
  4. There is only one duplicate number in the array, but it could be repeated more than once.

思路

包含有n+1个不大于n的正整数的数组一定存在重复元素,本题要求从这样的数组中找出重复的那个元素。题目很简单,有很多方法可做,但是难在要求空间复杂度O(1),时间复杂度小于O(n2),并且源数组是只读的,不允许任何修改操作。这样就限制了诸如Hash表,排序等的解法。最优解法是采用弗洛伊德循环寻找算法,原理如下:

  1. 需要明确一点:n+1个不大于n的正整数组成的数组可看做一个链表:
    • A[0]=1 >>>> A[1]=3 >>>> A[3]=2 >>>> A[2]=4 >>>> A[4]=2
i 0 1 2 3 4
A[i] 1 3 4 2 2

如果这样的数组中出现重复元素,那么这个链表就会出现一个环

  • A[0]=1 >>>> A[1]=3 >>>> A[3]=2 >>>> A[2]=4 >>>> A[4]=2
  1. 弗洛伊德循环寻找算法就是查找这个环入口的算法,过程为:
    (1)算法采用了一个慢指针和一个快指针,慢指针每次移动1步,快指针每次移动2步,初始两个指针都指向0,由于路径中存在环,两个指针最终肯定会汇合。第一次汇合时,我们将快指针重置为0,并将移动步数从2修改为1,等到两个指针再次汇合时,指向的元素即为环入口。
    (2)原理推导:如下图,P段表示链表中的非环部分,C表示慢指针与快指针第一次汇合时在环中重合的部分,L表是整个环的长度,X表示L-C部分;
    链表环
    (3)则当快指针与慢指针第一次汇合时,慢指针走过的路径长度为P+C,快指针走过的路径长度为L+C+nL(n为整数,由于快指针速度快,因此快指针一定是比慢指针多跑了n圈);然后由于快指针的速度是慢指针速度的2倍,而他们经过的时间是相同的,因此路程有如下关系:
    P + C + n L = 2 (
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/500352
推荐阅读
相关标签
  

闽ICP备14008679号