[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:
- You must not modify the array (assume the array is read only).
- You must use only constant, O(1) extra space.
- Your runtime complexity should be less than O(n2).
- There is only one duplicate number in the array, but it could be repeated more than once.
这道题给了我们 n+1 个数,所有的数都在 [1, n] 区域内,首先让证明必定会有一个重复数,这不禁让博主想起了小学华罗庚奥数中的抽屉原理(又叫鸽巢原理),即如果有十个苹果放到九个抽屉里,如果苹果全在抽屉里,则至少有一个抽屉里有两个苹果,这里就不证明了,直接来做题吧。题目要求不能改变原数组,即不能给原数组排序,又不能用多余空间,那么哈希表神马的也就不用考虑了,又说时间小于 O(n2),也就不能用 brute force 的方法,那也就只能考虑用二分搜索法了,在区间 [1, n] 中搜索,首先求出中点 mid,然后遍历整个数组,统计所有小于等于 mid 的数的个数,如果个数小于等于 mid,则说明重复值在 [mid+1, n] 之间,反之,重复值应在 [1, mid-1] 之间,然后依次类推,直到搜索完成,此时的 low 就是我们要求的重复值,参见代码如下:
解法一:
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int left = , right = nums.size();
while (left < right){
int mid = left + (right - left) / , cnt = ;
for (int num : nums) {
if (num <= mid) ++cnt;
}
if (cnt <= mid) left = mid + ;
else right = mid;
}
return right;
}
};
经过热心网友 waruzhi 的留言提醒还有一种 O(n) 的解法,并给了参考帖子,发现真是一种不错的解法,其核心思想快慢指针在之前的题目 Linked List Cycle II 中就有应用,这里应用的更加巧妙一些,由于题目限定了区间 [1,n],所以可以巧妙的利用坐标和数值之间相互转换,而由于重复数字的存在,那么一定会形成环,用快慢指针可以找到环并确定环的起始位置,确实是太巧妙了!
解法二:
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int slow = , fast = , t = ;
while (true) {
slow = nums[slow];
fast = nums[nums[fast]];
if (slow == fast) break;
}
while (true) {
slow = nums[slow];
t = nums[t];
if (slow == t) break;
}
return slow;
}
};
这道题还有一种位操作 Bit Manipulation 的解法,也十分的巧妙。思路是遍历每一位,然后对于 32 位中的每一个位 bit,都遍历一遍从0到 n-1,将0到 n-1 中的每一个数都跟 bit 相 ‘与’,若大于0,则计数器 cnt1 自增1。同时0到 n-1 也可以当作 nums 数组的下标,从而让 nums 数组中的每个数字也跟 bit 相 ‘与’,若大于0,则计数器 cnt2 自增1。最后比较若 cnt2 大于 cnt1,则将 bit 加入结果 res 中。这是为啥呢,因为对于每一位,0到 n-1 中所有数字中该位上的1的个数应该是固定的,如果 nums 数组中所有数字中该位上1的个数多了,说明重复数字在该位上一定是1,这样我们把重复数字的所有为1的位都累加起来,就可以还原出了这个重复数字,参见代码如下:
解法三:
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int res = , n = nums.size();
for (int i = ; i < ; ++i) {
int bit = ( << i), cnt1 = , cnt2 = ;
for (int k = ; k < n; ++k) {
if ((k & bit) > ) ++cnt1;
if ((nums[k] & bit) > ) ++cnt2;
}
if (cnt2 > cnt1) res += bit;
}
return res;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/287
类似题目:
Find All Numbers Disappeared in an Array
参考资料:
https://leetcode.com/problems/find-the-duplicate-number/
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] 287. Find the Duplicate Number 寻找重复数的更多相关文章
- 287 Find the Duplicate Number 寻找重复数
一个长度为 n + 1 的整形数组,其中的数字都在 1 到 n 之间,包括 1 和 n ,可知至少有一个重复的数字存在.假设只有一个数字重复,找出这个重复的数字.注意: 不能更改数组内容(假设数 ...
- LeetCode 287. Find the Duplicate Number (python 判断环,时间复杂度O(n))
LeetCode 287. Find the Duplicate Number 暴力解法 时间 O(nlog(n)),空间O(n),按题目中Note"只用O(1)的空间",照理是过 ...
- [LeetCode] Find the Duplicate Number 寻找重复数
Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), pro ...
- LeetCode 287. Find the Duplicate Number (找到重复的数字)
Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), pro ...
- [LeetCode] 287. Find the Duplicate Number 解题思路
Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), pro ...
- [LeetCode] 287. Find the Duplicate Number(Floyd判圈算法)
传送门 Description Given an array nums containing n + 1 integers where each integer is between 1 and n ...
- LeetCode : 287. Find the Duplicate Number
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAACRAAAAMMCAYAAAAhQhmZAAAMFGlDQ1BJQ0MgUHJvZmlsZQAASImVlw ...
- leetcode 217. Contains Duplicate 287. Find the Duplicate Number 442. Find All Duplicates in an Array 448. Find All Numbers Disappeared in an Array
后面3个题都是限制在1-n的,所有可以不先排序,可以利用巧方法做.最后两个题几乎一模一样. 217. Contains Duplicate class Solution { public: bool ...
- 287. Find the Duplicate Number hard
287. Find the Duplicate Number hard http://www.cnblogs.com/grandyang/p/4843654.html 51. N-Queens h ...
随机推荐
- Django学习笔记(19)——BBS+Blog项目开发(3)细节知识点补充
本文将BBS+Blog项目开发中所需要的细节知识点进行补充,其中内容包括KindEditor编辑器的使用,BeautifulSoup 模块及其防XSS攻击,Django中admin管理工具的使用,me ...
- 解决Git 克隆代码 The remote end hung up unexpectedly错误
从GitHub上克隆一个项目一直不成功!猜想可能是文件太大超时或者网络太慢超时! 解决方案: 配置 git config -- git config -- 增加最低速时间,but,还是不行! 公司网络 ...
- git 创建标签 tag
1. git tag <name>就可以打一个新标签 加上-a参数来创建一个带备注的tag,备注信息由-m指定.如果你未传入-m则创建过程系统会自动为你打开编辑器让你填写备注信息. git ...
- IDA分析时添加新的C语言结构体
View - Open Subviews - Local Type - INSERT键 - 输入新结构体 - 右击"Synchornize to idb" 之后再分析处按 T 就可 ...
- linq 数据库已存在,直接添加数据
using System.Data.Linq;using System.Data.Linq.Mapping; namespace ConsoleApplication1388{ class Progr ...
- django跳转页面传参
1.如果在反转url的时候,需要添加参数,那么可以通过传递'kwargs'参数到'reverse'函数中.实例代码: urls.py from django.urls import path, re_ ...
- 2019 奥买家java面试笔试题 (含面试题解析)
本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.奥买家等公司offer,岗位是Java后端开发,因为发展原因最终选择去了奥买家,入职一年时间了,也成为了面试官 ...
- IDEA创建父模块与子模块
1.IDEA点击New Project 2.点击+: 3.在[project]包下新建一个模块Moudle,名叫(springcloud)//root模块 4.继续添加模块Initializr持续ne ...
- Docker Desktop for Windows 安装步骤
Docker Desktop for Windows 安装要求 Docker Desktop for Windows需要运行Microsoft Hyper-V.如果需要,Docker Desktop ...
- HttpHelper之我见
前几月一直用一个Http的访问类去调用WebApi,说句实话最开始没觉有什么,一是技术老,二是觉得比较简单,但是最近我一直关注云开发和AI这块儿微软技术,看到云平台调用API大多类似,所以回想这个早年 ...