本题使用了抽屉算法,抽屉算法又名鸽巢原理,如果n+1个物体被放进n个盒子,那么至少有一个盒子包含两个或更多的物体。
比如
有8(1-7)个数字要在这些个抽屉里放,那么这个抽屉里会有一个重复
首先,mid=(left+right)/2=4,本来按道理来说,小于等于4的元素个数应该就是4,但是现在发现小于等于4的一共有5个>mid,说明在[0,left-mid]中会出现重复元素。同理,如果小于等于4的元素等于mid,说明重复的元素会出现在[mid+1,right]。
class Solution {
public int findDuplicate(int[] nums) {
int len = nums.length;
int left = 1;
int right = len - 1;
while (left < right) {
int mid = left + (right - left) / 2;
int cnt = 0;
//统计nums中有多少数是小于mid的
for (int num : nums) {
if (num <= mid) {
cnt += 1;
}
}
//如果个数大于mid,说明重复的数字就在1-mid中间。如果小于mid,说明重复数字在mid-right之间
if (cnt > mid) {
// 重复元素位于区间 [left..mid]
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
}