LeetCode | 287. 寻找重复数
特别感谢LeetCode大佬陈牧远的科普知识
给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。
示例 1:
输入: [1,3,4,2,2]
输出: 2
示例 2:
输入: [3,1,3,4,2]
输出: 3
说明:
- 不能更改原数组(假设数组是只读的)。
- 只能使用额外的 O(1) 的空间。
- 时间复杂度小于 O(n2) 。
- 数组中只有一个重复的数字,但它可能不止重复出现一次。
解析:
【笔记】这道题(据说)花费了计算机科学界的传奇人物Don Knuth
24小时才解出来。并且我只见过一个人(注:Keith Amling
)用更短时间解出此题。
快慢指针,一个时间复杂度为O(N)
的算法。
- 其一,对于链表问题,使用快慢指针可以判断是否有环。
- 其二,本题可以使用数组配合下标,抽象成链表问题。但是难点是要定位环的入口位置。
举个例子:nums = [2,5, 9 ,6,9,3,8, 9 ,7,1]
,构造成链表就是:2->[9]->1->5->3->6->8->7->[9]
,也就是在[9]
处循环。
- 其三,快慢指针问题,会在环内的
[9]->1->5->3->6->8->7->[9]
任何一个节点追上,不一定是在[9]
处相碰,事实上会在7
处碰上。 - 其四,必须另起一个
for
循环定位环入口位置[9]
。这里需要数学证明。
对“其四”简单说明一下,既然快慢指针在环内的某处已经相碰了。那么,第二个for
循环遍历时,res
指针还是在不停的绕环走,但是必定和i
指针在环入口处相碰。
双指针:
class Solution {
public:
int findDuplicate(vector<int>& nums) {
int res = 0;
for (int fast = 0; res != fast || fast == 0;){
res = nums[res];
fast = nums[nums[fast]];
}
cout << res;
for (int i = 0; res != i; i = nums[i]){
res = nums[res];
}
return res;
}
};
二分查找
class Solution {
public:
int findDuplicate(vector<int> &nums) {
int len = nums.size();
int left = 0;
int right = len - 1;
while (left < right) {
int mid = left + (right - left) / 2;
int cnt = 0;
for (int num:nums) {
if (num <= mid) {
cnt++;
}
}
// 根据抽屉原理,小于等于 4 的数的个数如果严格大于 4 个,
// 此时重复元素一定出现在 [1, 4] 区间里
if (cnt > mid) {
// 重复的元素一定出现在 [left, mid] 区间里
right = mid;
} else {
// if 分析正确了以后,else 搜索的区间就是 if 的反面
// [mid + 1, right]
// 注意:此时需要调整中位数的取法为上取整
left = mid + 1;
}
}
return left;
}
};
LeetCode | 287. 寻找重复数的更多相关文章
- Java实现 LeetCode 287 寻找重复数
287. 寻找重复数 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 ...
- leetcode 287寻找重复数
这道题用STL容器就很好写了,可以用set也可以用map, 用unordered_map的C++代码如下: class Solution { public: int findDuplicate(vec ...
- [LeetCode]287. 寻找重复数(二分)
题目 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 1: 输入: [ ...
- LeetCode:寻找重复数【287】
LeetCode:寻找重复数[287] 题目描述 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数 ...
- Leetcode之二分法专题-287. 寻找重复数(Find the Duplicate Number)
Leetcode之二分法专题-287. 寻找重复数(Find the Duplicate Number) 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 ...
- 287. 寻找重复数 Java解法
287. 寻找重复数 这题的难点就在于下面的说明了,我们先不管下面的那些说明的要求,用常规的解法来解答下上的题目. 排序思想解法 先把原来的数组进行排序,然后逐个遍历,一旦发现后一个元素和当前的元素相 ...
- 【Leetcode】287. 寻找重复数(数组模拟链表的快慢指针法)
寻找重复数 根据题意,数组中的数字都在1~n之间,所以数字的范围是小于数组的范围的,数组的元素可以和数组的索引相联系. 例如:nums[0] = 1 即可以将nums[0]作为索引 通过nums[0] ...
- 【leetcode】287. 寻找重复数
题目链接:传送门 题目描述: 给定一个数组 nums 包含 n + 1 个整数,每个整数在 1 到 n 之间,包括 1 和 n.现在假设数组中存在一个重复的数字,找到该重复的数字. 注意 不能修改数组 ...
- Leetcode题目287.寻找重复数(中等)
题目描述: 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数. 示例 1: 输入 ...
随机推荐
- springboot oauth 鉴权之——授权码authorization_code鉴权
近期一直在研究鉴权方面的各种案例,这几天有空,写一波总结及经验. 第一步:什么是 OAuth鉴权 OAuth2是工业标准的授权协议.OAuth2取代了在2006创建的原始OAuthTM协议所做的工作. ...
- 阿里云ECS 实例Centos7系统磁盘扩容
需求:一台阿里云的数据盘磁盘空间不足,需要扩容,我这里只有一个主分区,ext4文件系统. 因为磁盘扩容场景不同,阿里云的文档比较全面一些,所以先奉上阿里云的文档,下面开始我的操作步骤: 1.登录控制台 ...
- zctf 2016 android writeup - Jieming的博客
本文为2016年zctf中android的writeup. 首先点我下载题目.使用jeb反编译,对username和password进行部分验证后,再将username+password及一个数据库查 ...
- 当学术邂逅浪漫 – 记MobiCom 2015大会
作者:微软亚洲研究院主管研究员 刘云新 今年的MobiCom大会在著名的浪漫之都巴黎举行.通常于欧洲举办的会议的参会人数会相对少一些,但今年的MobiCom大会吸引了近400人参加,绝不少于往年.浪漫 ...
- OpenCV3入门(十一)图像直方图
1.直方图的概念 灰度直方图是灰度级的函数,描述的是图像中具有该灰度级的像元的个数.确定图像像素的灰度值范围,以适当的灰度间隔为单位将其划分为若干等级,以横轴表示灰度级,以纵轴表示每一灰度级具有的像素 ...
- Spark中Task数量的分析
本文主要说一下Spark中Task相关概念.RDD计算时Task的数量.Spark Streaming计算时Task的数量. Task作为Spark作业执行的最小单位,Task的数量及运行快慢间接决定 ...
- firewalls 开放端口
# 1. 开放 tcp 80 端口 firewall-cmd --zone=public --add-port=10080/tcp --permanent # 2. 开放 10080 ~ 65535 ...
- 一个基于Bootstrap实现的HMTL可视化编辑工具
疫情禁足在家,用原生的JS实现了一个HTML可视化编辑工具,页面布局基于Bootstrap.大约一个月时间,打通主要技术关卡,实现了第一版: 可以拖放编辑,实现了几乎所有的bootstrap预定义 ...
- boostrap3 bootstrap-datetimepicker.min.js设置中文语言
问题 bootstrap3中使用bootstrap-datetimepicker遇到设置中文语言的问题 解决办法 bootstrap-datetimepicker在使用的时候要先引入momentjs中 ...
- python之路-基本数据类型之str字符串
1.概念 python中用',",''',"""引起来的内容称为字符串,可以保存少量数据并进行相应的操作 #先来看看str的源码写了什么,方法:按ctrl+鼠标 ...