剑指 Offer 53 - II. 0~n-1中缺失的数字

一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

示例 1:


输入: [0,1,3]
输出: 2

示例 2:

输入: [0,1,2,3,4,5,6,7,9]
输出: 8

限制:

1 <= 数组长度 <= 10000

解法一:
二分设置left=0,right=nums.length-1,以及mid。
如果(left,mid]之间有缺失数字,则有
nums[mid]-nums[left] != mid - left;
则令right=mid(因为此时的mid仍有可能是缺失数字后的第一位)

如果(left,mid]之间没有,则说明缺失数字在(mid, right],
则令left=mid(因为此时的mid不可能是缺失数字后的第一位)

接下来确定while()的内容。我们想要的是情况是(左,右], 左是正常,右是缺失后的一位。故设定while内容 left+1<right
返回内容是nums[right]=right+1,故缺失数字为right。

但是这个思路有bug,即当缺失数字为0和n时,不能够确定。所以需要提前判断。

总的代码为:

class Solution {
    public int missingNumber(int[] nums) {
        int left = 0;
        int right = nums.length-1;
        if(nums[0]!=0) return 0;
        if(nums[right]!=right+1) return right+1;

        while(left+1<right){
            int middle = left + (right-left)/2;
            if(nums[middle]-nums[left] == middle-left){
                left = middle;
            }else{
                right=middle;
            }
        }
        return right;
    }
}

思路2:
如果没有缺失数字,则有nums[i]=i;故题目的目的就是找出第一个nums[i]!=i的数字。
设置left=0,right=nums.length;
有效区间为[left, right]
如果有nums[mid]=mid,则说明[left,mid]段内ok,错误在(mid,right]内,令left = mid + 1;
否则,说明[left, mid]内不ok,令right = mid
定义left<right
返回right

class Solution {
    public int missingNumber(int[] nums) {
        int left = 0;
        int right = nums.length;
        while(left<right){
            int mid = left + (right-left) / 2;
            if(nums[mid]==mid){
                left = mid + 1;
            }else{
                right = mid;
            }
        }
        return right;
    }
}
posted @ 2022-03-14 14:45  啤酒加点醋  阅读(35)  评论(0)    收藏  举报