- 剑指Offer53-Ⅱ.0~n-1中缺失的数字
- 题目:
一个长度为n-1的排序数组,数字都是[ 0,n - 1 ];
每个数字仅出现一次,找出那个唯一缺失的数字;
注:通常习惯与数组长度为n,总之题目表达的意思是,长为n的数组,值得范围均在[ 0,n ],即n个坑想放n+1个数,则一定有且仅有一个数不存在;下面均以数组长度为n解释;
- 思路:
1.遍历一次,找到第一个值和下标不同的位置:时间O(n),空间O(1)
长为n的数组下标范围:[0,n - 1 ],若数字都放在正确的位置,则缺失的就是n;否则一定由于某个数字缺失,而导致往后全部数字下标与数字不符,则第一个不符位置的下标就是缺失的数字;
class Solution {
public:
int missingNumber(vector<int>& nums) {//以长为4的数组,值均在[0, 4]举例
int n = nums.size();
for (int i = 0; i < n; ++i) {
if (i != nums[i]) return i;//0,2,3,4则缺1,从下标1处开始后面全部下标与值不符
}
return n;//0,1,2,3缺4
}
};
2.二分:O(logn)
根据方法1的分析,nums可分成左右部分,左边都是相符的,右边都是不相符的;;
本题等价于寻找数组nums中"nums[ i ] != i "的区间的左边界;
class Solution {
public:
int missingNumber(vector<int>& nums) {
int n = nums.size();
int l = 0, r = n - 1;
while (l <= r) {
int mid = l + ((r - l) >> 1);
//如果mid刚好是目标区间的左边界,则r就停在了左边界的左边,之后l不断靠近r,最后l==r时,l=mid+1退出循环,此时l指向目标区间的左边界,r=l-1;
//如果mid是目标区间的中间某个位置,则r=mid-1后,目标区间的左边界仍然包含在当前[l,r]区间内
if (nums[mid] != mid) r = mid - 1;
else l = mid + 1;
}
return l;//包含了[0,n-1]全部相符,缺失n的情况
}
};