【LeetCode题解】LeetCode 287. 寻找重复数
【题目链接】
287. 寻找重复数
【题目描述】
【题解】
定义cnt[i]cnt[i]cnt[i]表示numsnumsnums数组中小于等于iii的数有多少个,假设我们重复的数是targettargettarget,那么 [1,target−1][1,target−1][1,target−1]里的所有数满足cnt[i]≤icnt[i]≤icnt[i]≤i,[target,n][target,n][target,n]里的所有数满足cnt[i]>icnt[i]>icnt[i]>i,具有单调性。因此可以使用二分算法。
每次计算mid=(l+r)>>1mid = (l + r) >> 1mid=(l+r)>>1。计算cnt[mid]cnt[mid]cnt[mid],即数组中小于等于midmidmid的数字的个数。如果cnt[mid]>midcnt[mid] > midcnt[mid]>mid,说明重复的数字在区间[mid,n][mid, n][mid,n]内,调整l=mid+1l = mid + 1l=mid+1;否则,重复数字在[1,mid−1][1, mid-1][1,mid−1]内,调整r=mid−1r = mid - 1r=mid−1。
继续这个过程直到找到重复数字。
【AC代码】
class Solution {
public:int findDuplicate(vector<int>& nums) {int n = nums.size();int l = 1, r = n - 1, ans = -1;while (l <= r) {int mid = (l + r) >> 1;int cnt = 0;for (int i = 0; i < n; ++i) {if(nums[i] <= mid)cnt++;}if (cnt <= mid) {l = mid + 1;} else {r = mid - 1;ans = mid;}}return ans;}
};
【思考&收获】
二分的题,当你找到要对什么进行二分的时候,就已经成功一半了。