(No.5)前端写算法之--找到所有数组中消失的数字

63 阅读2分钟

二话不说,leetcode HOT100先开干,加油冲冲冲!这次开撕的是--找到所有数组中消失的数字。难度:简单

题目:给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。

/*  示例1: 
    输入: nums = [4,3,2,7,8,2,3,1]
    输出: [5,6]
*/
/*  示例2: 
    输入: nums = [1,1]
    输出: [2]
*/

思路:这道题很容易想到使用哈希表存储,可以将题目理解为将数组中的数据放在正确的位置上即可,如:[4,3,2,7,8,2,3,1]中,第一个4对应的下标应该为3,最后一项1对应的下标应该为0,那么就是说第i项应该放在i-1的位置,所以推导出:nums[i] = i - 1

答案1:基于存储:

var findDisappearedNumbers = function(nums) {
   const len = nums.length;
   const obj = {},res = []
   for(let i = 0; i < len; i++){
       obj[nums[i] -1] = nums[i] // 正确下标存入key,正确值存入vaule
       //此时如果nums=[4,3,2,7,8,2,3,1],则obj={0:1,1:2,2:3,3:4,6:7,7:8}
   }
   for(let i = 0; i < len; i++){
       if(obj[i]!==i+1){
           res.push(i+1) // 因为obj已正确顺序存入,所以当obj[i]!==i+1时,说明当前值不存在,存入res
       }
   }
   return res
};// 时间复杂度O(n),空间复杂度O(n)

答案2:进一步将空间复杂度降至O(1),找到正确的下标,将其下标对应的数据加上数组的长度,那么当前这个数据一定大于数组长度,后续判断如果不大于的,则说明该数据未存在

var climbStairs = function(n) {
    const len = nums.length;
    const res = []
    for(let i = 0; i < len; i++){
        const x = (nums[i]-1) % len //nums[i]-1找出当前正确下标,
        // % len是因为nums[i]-1这个下标会在下一步加上了数组长度,所以应该将他恢复至原始数据在进行判断
        nums[x] += len
    }
    for(let i = 0; i < len; i++){
        if(nums[i]<=len) res.push(i+1) // 将小于等数组长度的数据存入res
    }
    return res
}; // 时间复杂度O(n),空间复杂度O(1)

答案2:易懂版

var climbStairs = function(n) {
// 易懂版
    const len = nums.length
   let i = 0,res=[];
    while (i < nums.length) {
        if (nums[i] == i + 1) { // 当当前数组数值=正确下标时,跳过
            i++;
            continue;
        }
        const idealIdx = nums[i] - 1; // 获取当前数值正确的下标
        if (nums[i] == nums[idealIdx]) { // 当正确下标下的数值已经是正确数值的时候,跳过
            i++;
            continue;
        }
        [nums[idealIdx], nums[i]] = [nums[i], nums[idealIdx]]; // 交换两个值
        //此时不需要i++,因为重新交换后的数据需要重新校验一次
    }
    for(let j = 0; j < len; j++){
        if(nums[j]!==j+1){
            res.push(j+1)
        }
    }
    return res
}; // 时间复杂度O(n),空间复杂度O(1)