LeetCode 287. Find the Duplicate Number (时间复杂度O(n)) + 链表判断环
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),思路十分巧妙,但是使用条件比较苛刻。根据题目给出的条件,恰好能用这种解法,这应该也是出题人推荐的解法。
题意分析:
- 输入的序列有n+1个数字,每个数字在1~n之间取,这为构成数字环创造了条件。
- 只有一个数字有重复,所以只可能构成一个环。
注:上面所说的环是指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)) + 链表判断环相关推荐
- LeetCode.287 Find the Duplicate Number
题目: Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), ...
- LeetCode 287. Find the Duplicate Number
题目: Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), ...
- leetcode 287. Find the Duplicate Number | 287. 寻找重复数(判断链表是否有环,并找到环的起点)
题目 https://leetcode.com/problems/find-the-duplicate-number/ 题解 题目有限制 不能修改数组元素,必须 O(1) 空间复杂度,所以 不能排序, ...
- 287. **Find the Duplicate Number
287. **Find the Duplicate Number https://leetcode.com/problems/find-the-duplicate-number/description ...
- 287. Find the Duplicate Number
Title 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 1: 输入 ...
- LeetCode 287---Find the Duplicate Number
问题链接:LeetCode 287-Find the Duplicate Number 题目大意 : 找出序列中唯一一个重复出现的数字,且只能使用o(1)的额外空间 实现代码如下: public cl ...
- LintCode Find the Duplicate Number
Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), pro ...
- D19:Duplicate Number(重复数字,翻译+题解)
原题:OpenJudge - 19:Duplicate Number 翻译: 描述:给定一个N个数的序列,求一个在序列中的至少出现2次的数A: 输入:第一行:一个不大于1000的正整数N : 第二行: ...
- leetcode【537】Complex Number Multiplication(复数相乘)
写在最前面:一道很常规的字符串分割的题 leetcode[537]Complex Number Multiplication Given two strings representing two co ...
最新文章
- ccna考试真题及经验介绍
- Flutter framework在线上构建时的包大小优化
- [pytorch] 官网教程+注释
- 数学在机器学习中的重要性[by Dahua Lin]
- SharePoint 2013 图文开发系列之WebPart
- UE4学习-游戏退出、游戏打包
- 二分查找和折半插入排序一块说说-很合适~~~
- java ee程序设计师_软件设计师:Java EE开发四大常用框架[1]
- 电脑屏幕卡住了按什么都没反应_90%的电脑问题都能解决,只要学会这8个字!...
- mysql 防止网络爬虫_Nginx反爬虫策略,防止UA抓取网站
- 如何利用python实现qq聊天_Python之路 - Socket实现QQ聊天
- 省赛前的做题计划记录
- Python练手项目:玩转魔方
- 为宠物提供鲜粮,超能小黑完成2000万元A轮融资
- HTML+CSS网页制作——人生指南
- 我套你猴子的,哥上岸了!附上我的字节客户端开发面经,希望帮助到大家!
- Sqlmap参数详解
- C++调用python,并抓取每日一句名言
- oracle判断是否是手机号码,oracle存储过程判断手机号码和固话
- 大学计算机课试题答案,大学计算机基础试题及答案课件.doc
热门文章
- 每日程序C语言15-猴子吃桃问题
- 为什么parsefloat加出来还是字符串_为什么酒店的包子做的这么好吃?里面加了什么说出来你可能不信...
- thymeleaf 中文_springboot 整合 thymeleaf(上手即用)
- oracle 02380,oracle 11.2.0.3 fornb…
- OpenCV C++ 01 - Load Image from File and Display
- 数位dp模板 [dp][数位dp]
- 特权同学笔记-榨干FPGA片上存储资源
- 使用Volley StringRequest Get的方式进行发票查询操作
- 把Sql数据转换为业务数据的几种方法
- ftp服务器如何复制文件路径,ftp服务器上复制文件路径