LeetCode
- 题目地址:https://leetcode.com/problems/find-the-duplicate-number/#/description
问题描述&解题思路:给一个n+1大小的数组,其中这些整数都在1到n之中,假设只有一个数字会有重复(不一定只重复一次),求出这个重复的数字。如果只有只重复一次可以用抑或来做,如果重复的数字大于一半,那么遍历一次即可,但是这里都没有这样的条件,前两种条件下都是O(n)复杂度的。
- 于是思考1,先将1到n置为false,然后遍历数组,如果对应的b为false则置为true,如果不是,则返回该数字(说明之前有出现过这个数字),但是题目加了限制,只能使用O(1)的额外空间,那么这里还是给了代码
- 思考2,参考solution,采用二分的办法,每次取中间数mid = (low+high)/ 2,然后数有多少个数字小于等于中间数的,如果小于中间数的数目太少(数目小于mid),说明重复的数在比 mid大的那一半数中,否则说明在小于等于中间数的那一半数中。由于二分,这样的过程要执行O(logn)次,每次需要遍历一次数组,所以是O(nlogn)的复杂度
思考1
int findDuplicate(vector<int>& nums) {
//all are false at begin
bool b[nums.size()-1];
memset(b,0,sizeof(b));
for (int i = 0, size = nums.size(); i < size; i++) {
if (!b[nums[i]-1])
b[nums[i]-1] = true;
else
return nums[i];
}
}
- 思考2
int findDuplicate(vector<int>& nums) {
int low = 1, high = nums.size()-1;
int size = nums.size();
while (low < high) {
int mid = (low + high) / 2;
int count = 0;
for (int i = 0; i < size; i++) {
if (nums[i] <= mid)
count++;
}
if (count > mid) {
high = mid;
} else {
low = mid + 1;
}
}
return high;
}