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;
            }
        }

 

、、

 

posted @ 2021-10-06 23:01  CharonKK  阅读(41)  评论(0)    收藏  举报