代码如下:
/**
* 二分法
*
* 根据二分法特征,左右指针向中间靠拢
* 计算出中位数,并在中间的子区间中累加比中位数小于等于的数
* 如果累加出来的结果要比理论上的中位数大,说明前半边的区间有多的元素,即重复的数
* 如果比理论值mid小,说明重复的数在右半边
* 根据以上判断,在每次循环结尾更改指针的位置
*
* Code by java
*/
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) >>> 1; // 无符号右移防越界
// int mid = left + (right - left) / 2; //也可以这么做
int cnt = 0;
for (int num : nums) {
if (num <= mid) {
cnt += 1;
}
}
// cnt比中位数大,说明在前半边的区间内,有多的元素,即重复的数,所以把空间缩小到左半边
if (cnt > mid) {
// 重复元素位于区间 [left, mid]
right = mid;
} else {
// [mid + 1, right]
left = mid + 1;
}
}
return left;
}
public static void main(String[] args) {
Solution a = new Solution();
int[] p = new int[] { 3, 1, 3, 4, 2 };
System.out.println(a.findDuplicate(p));
}
}