Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
一、题目描述:
数组包含从0到n的所有整数,但其中缺了一个,找出那个缺失的整数。
输入: [3,0,1]
输出: 2
数组包括0到3,其中缺少2。
二、思路分析:
根据题目我们知道,数组里面的值是0~n,那么数组的索引也是0~n,根据这个思路,我们可以根据索引找到对应的值,判断值存不存在。
function missingNumber (nums) {
let set = new Set()
for (let i = 0; i < nums.length; i++) {
set.add(nums[i])
}
for (let i = 0; i < nums.length; i++) {
if (set.has(i) === false) {
return i
}
}
return 0
}
使用set标记法,来判断值是否存在。时间复杂度位O(n),空间复杂度位O(n)。
除了标记法,我们还可以对数组进行排序,排序后遍历数组,数组索引与对应的值对比,不相同就输出。
function missingNumber (nums) {
let arr = nums.sort((a, b) => a - b)
for (let i = 0; i < nums.length; i++) {
if (arr[i] !== i) {
return i
}
}
return 0
}
使用排序法,来判断值是否存在。时间复杂度位O(NloginN)。
上面两种发放都不是最好的,第三方方法是等差数列求和公式。
现在有个等差数列 0, 1, 2,…, n, 其中少了某⼀个数字, 请你把它找出来。 那这个数字不就是 sum(0,1,…n) - sum(nums)嘛?
function missingNumber (nums) {
let n = nums.length
let expect = (0 + n) * (n + 1) / 2
let total = nums.reduce((a, b) => a + b, 0)
return expect - total
}
等差数列求和公式,前n项和公式为:Sn=n*a1+n(n-1)d/2或Sn=n(a1+an)/2 。
通过等差数列求和是找一个消失数字的最佳实践方法。
到目前为止我们已经掌握了找一个消失的数字,那么加大题目难度,找到所有数组中消失的数字。
function missingNumber (nums) {
let set = new Set()
let res = []
for (let i = 0; i < nums.length; i++) {
set.add(nums[i])
}
for (let i = 0; i <= nums.length; i++) {
if (set.has(i) === false) {
res.push(i)
}
}
return res
}
通过简单的修改一下代码就可以实现,也是使用 set 来标记。
我们用一个哈希表记录数组 nums 中的数字,由于数字范围均在 [0,n] 中,记录数字后我们再利用哈希表检查 [0,n] 中的每一个数是否出现,从而找到缺失的数字。
四、总结:
在算法的实现过程中其实经常使用哈希表记录数组的数字,但是会导致空间复杂度变成O(n),所以在编写算法的时候要检查自己的代码是否可以降低复杂度,看下是否可以通过数学公式来完成计算。