LeetCode 287. Find the Duplicate Number

暴力解法

时间 O(nlog(n)),空间O(n),按题目中Note“只用O(1)的空间”,照理是过不了的,但是可能判题并没有卡空间复杂度,所以也能AC。

class Solution:# 基本思路为,将第一次出现的数字def findDuplicate(self, nums: List[int]) -> int:s = set()for i in nums:a = i in sif a == True:return ielse:s.add(i)

双指针判断环

时间O(n),空间O(1),思路十分巧妙,但是使用条件比较苛刻。根据题目给出的条件,恰好能用这种解法,这应该也是出题人推荐的解法。

题意分析:

  1. 输入的序列有n+1个数字,每个数字在1~n之间取,这为构成数字环创造了条件。
  2. 只有一个数字有重复,所以只可能构成一个环。

注:上面所说的环是指1->2->3->1

以样例1为例:[1,3,4,2,2]

0 1 2 3 4
1 3 4 2 2

如下图所示,其中2->4->2构成环,入环点为2

解题思路

由题意分析可知,每个样例都可以画成这样一张图,我们只需要找出图中的环,并找出入环点,即为所求的重复数字key,下面都用key表示所求的重复数字。

为什么必定存在环

以样例1为例,图中出现了5个点0-4,图中存在5根指针线,5个点5根线,必定存在环。
n个点,点的范围去0~n-1,n根线,必定存在环。(n-1根线是恰好无环的情况,自己画图可知)

找环的方法

设置一个慢指针slow,一个快指针fast。slow每次走一步,fast每次走两步,如果slow与fast能相遇,说明图中存在环,并且相遇点一定存在于环中。

为什么key一定为入环点?

有题意分析中的表可知,key的入度一定大于1,即不止一个点可以直接到key。而key一定存在于环中,所以key一定为入环点。样例1中3,4都可到达2,2的入度2,2为入环点,即为所求的key。

怎么找入环点key?

slow和fast相交的点记为相遇点P。
slow和fast从起点0到相遇点P运行步骤如下:

这个相遇点P与起点0到达入环点key的步数 差距为环L的整数倍,故设置slow2从起点0开始,每次走一步,slow从相遇点P开始,每次走一步,slow和slow2一定会相遇在入环点key。

我们可以有一个小小的证明,如下图

设起点0到达入环点key的步数为x,相遇点P到达入环点key的步数为y。
设slow指针走到相遇点P的步数为t,fast走到相遇点P的步数为2*t。
设走完环一圈的步数为L

2 * t - x + y = M * L(一)
t - x + y = N * L (二)
fast指针在环中走的步数2t-x,此时到达相遇点P,key->P->key步数为2t-x+y = M * L,正好为L的M倍,M为常数。(一)式
slow指针在环中走的步数t-x,此时到达相遇点P,key->P->key步数为t-x+y = N * L,正好为L的N倍,N为常数。(二)式

2倍(二)式 减 (一)式
y-x = (2N-M) * L
所以y与x的步数差距为L倍的环。
得证。

如何确定起点0一定会进入包含key的环?

假设存在不包含key的环,起点0在不包含key的环中绕圈。

0 a1 a2 a3 a4 a5 a6
b1 b2 b3 b4 b5 b6 b7

按题意不包含环,b[i]与b[j]一定不相等(i != j)
由于b1~b7从1开始,所以b[i]只能从a[j]中取(1<=i<=7,1<=j<=6)
从6个数字的集合a中取7个数字,所以假设不成立,必定存在相同数字b[k],即为key。

代码如下

class Solution:def findDuplicate(self, nums: List[int]) -> int:# 如果只有两个元素,第一个元素一定是重复元素if len(nums) == 2:return nums[0]# fast每次走两步,slow每次走一步,起始点可以为任意位置fast = 0slow = 0# python没有do while,所以在循环外写了一遍slow = nums[slow]fast = nums[nums[fast]]while slow != fast:slow = nums[slow]fast = nums[nums[fast]]# fast从起点每次走一步,一定会与slow相遇,此时slow可能在环中走了多倍的L步。# L为环一圈的步数fast = 0while fast != slow:slow = nums[slow]fast = nums[fast]return fast

LeetCode 287. Find the Duplicate Number (时间复杂度O(n)) + 链表判断环相关推荐

  1. LeetCode.287 Find the Duplicate Number

    题目: Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), ...

  2. LeetCode 287. Find the Duplicate Number

    题目: Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), ...

  3. leetcode 287. Find the Duplicate Number | 287. 寻找重复数(判断链表是否有环,并找到环的起点)

    题目 https://leetcode.com/problems/find-the-duplicate-number/ 题解 题目有限制 不能修改数组元素,必须 O(1) 空间复杂度,所以 不能排序, ...

  4. 287. **Find the Duplicate Number

    287. **Find the Duplicate Number https://leetcode.com/problems/find-the-duplicate-number/description ...

  5. 287. Find the Duplicate Number

    Title 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 1: 输入 ...

  6. LeetCode 287---Find the Duplicate Number

    问题链接:LeetCode 287-Find the Duplicate Number 题目大意 : 找出序列中唯一一个重复出现的数字,且只能使用o(1)的额外空间 实现代码如下: public cl ...

  7. LintCode Find the Duplicate Number

    Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), pro ...

  8. D19:Duplicate Number(重复数字,翻译+题解)

    原题:OpenJudge - 19:Duplicate Number 翻译: 描述:给定一个N个数的序列,求一个在序列中的至少出现2次的数A: 输入:第一行:一个不大于1000的正整数N : 第二行: ...

  9. leetcode【537】Complex Number Multiplication(复数相乘)

    写在最前面:一道很常规的字符串分割的题 leetcode[537]Complex Number Multiplication Given two strings representing two co ...

最新文章

  1. ccna考试真题及经验介绍
  2. Flutter framework在线上构建时的包大小优化
  3. [pytorch] 官网教程+注释
  4. 数学在机器学习中的重要性[by Dahua Lin]
  5. SharePoint 2013 图文开发系列之WebPart
  6. UE4学习-游戏退出、游戏打包
  7. 二分查找和折半插入排序一块说说-很合适~~~
  8. java ee程序设计师_软件设计师:Java EE开发四大常用框架[1]
  9. 电脑屏幕卡住了按什么都没反应_90%的电脑问题都能解决,只要学会这8个字!...
  10. mysql 防止网络爬虫_Nginx反爬虫策略,防止UA抓取网站
  11. 如何利用python实现qq聊天_Python之路 - Socket实现QQ聊天
  12. 省赛前的做题计划记录
  13. Python练手项目:玩转魔方
  14. 为宠物提供鲜粮,超能小黑完成2000万元A轮融资
  15. HTML+CSS网页制作——人生指南
  16. 我套你猴子的,哥上岸了!附上我的字节客户端开发面经,希望帮助到大家!
  17. Sqlmap参数详解
  18. C++调用python,并抓取每日一句名言
  19. oracle判断是否是手机号码,oracle存储过程判断手机号码和固话
  20. 大学计算机课试题答案,大学计算机基础试题及答案课件.doc

热门文章

  1. 每日程序C语言15-猴子吃桃问题
  2. 为什么parsefloat加出来还是字符串_为什么酒店的包子做的这么好吃?里面加了什么说出来你可能不信...
  3. thymeleaf 中文_springboot 整合 thymeleaf(上手即用)
  4. oracle 02380,oracle 11.2.0.3 fornb…
  5. OpenCV C++ 01 - Load Image from File and Display
  6. 数位dp模板 [dp][数位dp]
  7. 特权同学笔记-榨干FPGA片上存储资源
  8. 使用Volley StringRequest Get的方式进行发票查询操作
  9. 把Sql数据转换为业务数据的几种方法
  10. ftp服务器如何复制文件路径,ftp服务器上复制文件路径