这是我参与8月更文挑战的第13天,活动详情查看: 8月更文挑战
题干
一个长度为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
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/qu… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解法:
看到这里我想了想,直接无脑循环找不适合当前的值的数(就是当前的元素于当前下标不等时)直接跳出循环返回结果。
var missingNumber = function (nums) {
for (let i = 0; i <= nums.length; i++) {
if(nums[i]!==i){
return i
}
}
return ''
};
写完以后,看了一下,发现了一句神评:“所有题都拿来遍历,offer也就遍历到别人那里去了”,笑死我了,原来我没有利用有序数组这个条件,虽然上面的解法也算是用到了有序,但是我们听到有序时,首先应该想到的还应该是二分法呀。
怎么二分呢?
首先我们清楚我们的数组中缺失了一个元素,所以它一定是两个连续的数组,我们就是要找到两个连续数组的交界处。
左子节点:nums[i]=i
右子节点:nums[i]!=i
因此二分的条件也就比较明确了:
middle[mid]==mid 说明目前是左子区间 mid=low+1
middle[mid]!=mid 说明目前是右子区间 mid=max-1
当我们跳出循环时,i和j最终就会指向右子区间的头开头和左子区间的结尾,所以我们直接返回i就可以
代码实现:
/**
* @param {number[]} nums
* @return {number}
*/
var missingNumber = function (nums) {
let low = 0;
let max = nums.length-1;
while (low <= max) {
var middle = Math.floor((low + max) / 2)
if (middle == nums[middle]) {
low = middle + 1
} else {
max = middle - 1
}
}
return low
};
\