[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 ...
随机推荐
- Leetcode 542:01 矩阵 01
Leetcode 542:01 矩阵 01 Matrix### 题目: 给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离. 两个相邻元素间的距离为 1 . Given a matr ...
- 基于Spark的电影推荐系统(推荐系统~7)
基于Spark的电影推荐系统(推荐系统~7) 22/100 发布文章 liuge36 第四部分-推荐系统-实时推荐 本模块基于第4节得到的模型,开始为用户做实时推荐,推荐用户最有可能喜爱的5部电影. ...
- FreeMarker实现网页静态化
1.FreeMarker实现网页静态化. FreeMarker是一个用Java语言编写的模板引擎,它基于模板来生成文本输出.FreeMarker与Web容器无关,即在Web运行时,它并不知道Servl ...
- efcore mysql数据库codefirst生成
添加引用 Microsoft.EntityFrameworkCore Microsoft.EntityFrameworkCore.Tools Pomelo.EntityFrameworkCore.My ...
- datalab (原发布 csdn 2018年09月21日 20:42:54)
首先声明datalab本人未完成,有4道题目没有做出来.本文博客记录下自己的解析,以便以后回忆.如果能帮助到你就更好了,如果觉得本文没啥技术含量,也望多多包涵. /* * bitAnd - x& ...
- C# - MD5验证
前言 本篇主要记录:VS2019 WinFrm桌面应用程序实现字符串和文件的Md5转换功能.后续系统用户登录密码保护,可采用MD5加密保存到后台数据库. 准备工作 搭建WinFrm前台界面 如下图 核 ...
- LinuxShell——认识BATH这个Shell
LinuxShell——认识BATH这个Shell 摘要:本文主要了解了Linux系统中的Shell,以及什么是BATH. 什么是Shell Shell是一个命令行解释器,它为用户提供了一个向Linu ...
- 014.统一建模语言UML
1.UML 的设计目的 UML是为了简化和强化现有的大量面向对象开发方法这一目的而开发的. UML 适用于各种软件开发方法.软件生命周期的各个阶段.各种应用领域以及各种开发工具,是一种总结了以往建模技 ...
- Facebook发布全新JavaScript引擎:Hermes
摘要: JS引擎开始升级了... 原文:技术栈中的爱马仕?Facebook发布全新JavaScript引擎:Hermes 作者:Carson_Ho Fundebug经授权转载,版权归原作者所有. 前言 ...
- Java常用算法总结
冒泡排序 从左到右不断交换相邻逆序的元素,在一轮的循环之后,可以让未排序的最大元素上浮到右侧. 在一轮循环中,如果没有发生交换,那么说明数组已经是有序的,此时可以直接退出. 代码如下: public ...