二分查找 02

62 阅读1分钟

LeetCode 287

原题链接

代码如下:

/**
 * 二分法
 * 
 * 根据二分法特征,左右指针向中间靠拢
 * 计算出中位数,并在中间的子区间中累加比中位数小于等于的数
 * 如果累加出来的结果要比理论上的中位数大,说明前半边的区间有多的元素,即重复的数
 * 如果比理论值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));
	}
}