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

题目

一个长度为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

分析与题解

题解一

假设 0~n-1 中没有数字 i ,那么这 n - 1 个数字的和为 sum = n(n-1)/2 - i,那么 i = n(n-1)/2 - sum。

代码如下:

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int size = nums.size();
        int sum=0;
        for(int i=0;i<size;i++)
        {
            sum+=nums[i];
        }
        int total = (1+size)*(size)/2;
        return (total-sum);
    }
};

题解二

因为要不重复地将0~n-1填入到n-1个空位中,所以首个下标与数组元素不等的位置,缺失的数值与当前下标相等。如果遍历数组后,所有下标都与其对应的数组元素相等,那么缺失的元素即为n-1。代码如下:

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int size = nums.size();
        for(int i=0;i<size;i++)
        {
            if(nums[i]!=i)
                return i;
        }
        return size;
    }
};

题解三

上述俩题解的时间复杂度均为 O(n)。与题解二类似,同样依赖于整个数组元素按照递增序列进行排序的。如果任意下标i与其对应数组元素相等,那么缺失的元素一定在i+1到n-1之间;如果不等,则缺失的数字在0~i之间。因此采用二分查找法思想去优化时间复杂度。

若i==nums[i],则下标i左边只有0~i-1可以使用,并且空位总数为i,又需要按照递增排序,所以位置确定无二义性

代码如下:

class Solution {
public:
    int missingNumber(vector<int>& nums) {
        int mid=0,left=0;
        int right=nums.size();
        while(left<right)
        {
            mid = (left+right)/2;
            if(nums[mid]==mid)
            //不确定是否为第一个下标不等的元素
            {
                left = mid+1;
            }
            else
            {
                right=mid;
            }
        }
        return left;
        //最后左右边界重合,输出任意一个边界
    }
};
posted @ 2020-07-29 16:35  脱线森林`  阅读(201)  评论(0编辑  收藏  举报