携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情
每日刷题 2022.08.11
- leetcode原题链接:leetcode.cn/problems/qu…
- 难度:简单
- 方法:二分
题目
- 一个长度为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之内。那么对于缺失的数据之前,一定满足nums[i] === i,而对于缺失的数据之后一定不满足nums[i] ==== i。因此可以使用二分,找到不满足的下标,输出即可。 - 类似的题目剑指 Offer 11. 旋转数组的最小数字,也是使用二分的解法,但是这里的二段性就比本题的要较为难理解一些。
二分
- 二分的本质是:二段性
- 根据题意可知,数据和数组下标是对应的,如果中间有缺失,则数据肯定比下标大,而且又是有序数组,利用二分查找,条件为
nums[mid]>mid - 遍历,当前的数
+ 1不等于下一个索引的数,则返回当前的数+ 1 - 特殊边界:第一个数不是
0的时候就是缺失0,到最后一个数的时候还没有return上面的正常情况就是缺失最后一个数+ 1。
AC代码
/**
* @param {number[]} nums
* @return {number}
*/
var missingNumber = function(nums) {
// 首先:长度为n-1,一共有n个数字,也就是包含长度在内的数字
// 有序的就需要二分,具有二段性,这个一定要想清楚。
// 有序的,那么缺失的前面一段,就是nums[i] = i, 缺失的后面一段就不满足nums[i] = i
let n = nums.length;
let idx = binary();
return idx;
function binary() {
let l = -1, r = n;
while(l + 1 != r) {
let mid = Math.floor((l + r) / 2);
if(mid === nums[mid]) {
l = mid;
} else {
r = mid;
}
}
return r;
}
};