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

Example 2:

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

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 (
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值