No.287 寻找重复数
287. 寻找重复数 - 力扣(LeetCode) (leetcode-cn.com)
思路:
注意:不可以按照 找数组中严格小于mid的数字的个数来判断重复数字的位置, nums[] = {1,2,2}的时候会陷入死循环
public int findDuplicate(int[] nums) { //二分法 //根据题意,数组长度为n, 其中的元素都在[1,n]中,且有一个是重复的。 // 那么,初始时候,可以用[1,n]这个范围的最中间那个mid来判断重复的数字位置(在mid的左边,或者右边) //判断的方法,就是计算整个数组中,比mid小的数字的个数,如果比mid小的数字,个数大于mid, //那么mid左边的数字就有重复的, 反之,mid右边的数字就有重复 //以此类推,第二次,就根据第一次得到的重复数的位置,设置新的mid值 (mid+left)/2 或者 (mid+right)/2 //直至找出最终答案 int len = nums.length; int left = 1; int right = len - 1; int mid = (left + right) / 2; if (left == 2) { return nums[0]; } while (left < right) { int count = 0; for (int i = 0; i < len; i++) { if (nums[i] <= mid) { //判断整个数组中,比mid要小的数字 count++; //不大于mid的数字个数 } } if (count > mid) { //严格大于mid的数字比预期的少,就是说[left,mid]区间的数字占用了右边的名额
//那么重复数字在mid的左边,(调整right和mid位置) [left, mid] right = mid; mid = (left + mid) / 2; } else { //严格大于mid的数字不低于预期(就是超过),那么重复数字就在(mid,right]之间 left = mid+1; mid = (mid + right) / 2; } } return left; }
这样会报错(1,2,2)不行,因为mid = ( right + left ) / 2,这个在单数的时候,mid会往左沉,可能导致和 left 重合,从而导致陷入死循环
while (left < right) { int count = 0; for (int i = 0; i < len; i++) { if (nums[i] < mid) { //判断整个数组中,比mid要小的数字 count++; } } if (count > mid) { //比mid严格小的数字比预期的多,那么重复数字在mid的左边,(调整right和mid位置) [left, mid) right = mid-1; mid = (left + mid) / 2; } else { //比mid小的数字和预期的一直(小于mid),那么重复数字就在[mid,right]之间 left = mid+1; mid = (mid + right) / 2; } }
、、

浙公网安备 33010602011771号