题目描述
一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1
之内。在范围0~n-1
内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。
思路
对于排序数字中查找,肯定考虑用二分查找最高效,时间复杂度为O(log n)。我们假设不在数组中的那个数字记为m
,那么所有m
小的数字的下标都与它们对应位置的值相同。由于m
不在数组中,所以m+1
处在下标为m
的位置,m+2
处在下标为m+1
的位置。
因此这个问题转化为在排序数组中找到第一个值和下标不相等的元素。
我们可以基于二分查找得到算法如下:
(1)如果中间元素的值和下标相等,下一轮查找只需要查找右半边
(2)如果中间元素的值和下标不等
a. 并且前一个元素和它的下标相等,这意味着这个中间数字正好是第一个值和下标不相等的元素,它的下标就是我们要找的值;
b. 否则,下一轮查找只需要查找左半边
代码
/*
* 转化为二分查找第一个值与下标不相等的元素
* 时间复杂度O(logn) 空间复杂度O(1)
*/
class Solution {
public:
int getMissingNumber(vector<int> nums){
if(nums.empty()) return 0;
int left = 0, right = nums.size()-1;
while(left <= right){
int mid = (left+right)/2;
if(nums[mid] != mid){
if(mid == 0 || (mid>0 && nums[mid-1]==mid-1)) // 如果元素与坐标不等且前一个元素与坐标相等
return mid; // 则该元素为第一个值与下标不相等元素
right = mid -1; // 左区间
} else
left = mid + 1; // 右区间
}
if (left == nums.size()-1) // 缺的是最后一个元素
return nums.size()-1;
return -1;
}
};