剑指 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 @   啤酒加点醋  阅读(26)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示