剑指 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;
//最后左右边界重合,输出任意一个边界
}
};