zoukankan      html  css  js  c++  java
  • [Leetcode]287. Find the Duplicate Number

    这是Leetcode第287题,给定一个包含n + 1个整数的数组,其中每一个整数均介于[1, n]之间,证明其中至少有一个重复元素存在。假设只有一个数字出现重复,找出这个重复的数字。
    这道题可以用计数排序的思路求解,但更为巧妙的方法是使用快慢指针求解。
    基本思想是将数组抽象为一条线和一个圆环,因为1~n 之间有n+1个数,所以一定有重复数字出现,所以重复的数字即是圆环与线的交汇点。然后设置两个指针,一个快指针一次走两步,一个慢指针一次走一步。当两个指针第一次相遇时,令快指针回到原点(0)且也变成一次走一步,慢指针则继续前进,再次回合时即是线与圆环的交汇点。

    快慢指针

    明白了上面的原型后,我们来看这个变型。把数组抽象成线和圆环,举例来说,假设我们有一个数组是nums[]=[1,2,3,4,5,5,6,7],pf代表快指针,ps代表慢指针,初始ps指向nums[0],即1,pf指向nums[nums[0]],即2,行动一次后,ps指向nums[1],即2,pf指向nums[nums[2]],即4,再动一次,ps指向nums[2],即3,pf则指向了nums[nums[4]],即5;可以发现pf一旦指向5后便不会再动,因为nums[5]一直为5,直到ps慢慢追上,然后令pf从头开始,ps一直在5处停留,最后定会相遇在这里,而这里就是重复数字。这里举了个最简单的例子,是为了方便大家理解,实际上实际的圆环顺序与数组的顺序是没有关系的,不信可以自己在纸上画一画,当数组变成nums[]=[4,6,5,1,3,2,5,7]的样子,你会更加理解这个算法的!

    具体代码如下:

    class Solution:
        def findDuplicate(self, nums: List[int]) -> int:
            for i in range(len(nums)):
                while nums[i] != i+1:
                    index= nums[i]-1
                    if nums[i] == nums[index]:
                        return nums[i]
                    else:
                        nums[i],nums[index] = nums[index],nums[i]
    

    快慢指针解法具体代码如下:

    class Solution:
        def findDuplicate(self, nums: List[int]) -> int:
            slow = 0
            fast = 0
            while True:
                slow = nums[slow]
                fast = nums[nums[fast]]
                if slow == fast:
                     break
            fast = 0
            while slow!=fast:
                slow   = nums[slow]
                fast = nums[fast]
        
            return slow
    

    快慢指针的题也很常见了,在求环问题中更是经典的解法。用数组索引来代表环的位置,也是一个很trick的思想。

  • 相关阅读:
    简单的react-dom.js react.js 中的源码手写
    回顾vue源码理解到哪记录到哪
    一道很有纪念意义的算法题之多维数组去重,不降维
    下载文件.xlsx .csv 或者下载压缩包
    koa+mysql简单实现查询功能
    幽灵空白节点解决方案,史上最明白
    useCallback,useMemo源码
    useContext源码解读
    useEffect源码
    Hadoop 学习笔记(二)Hadoop 本地运行环境搭建及简单应用
  • 原文地址:https://www.cnblogs.com/hellojamest/p/11622377.html
Copyright © 2011-2022 走看看