leecode 刷题 448. 找到所有数组中消失的数字(简单) | 刷题打卡

177 阅读2分钟

题目描述

给定一个范围在  1 ≤ a[i] ≤ n ( n = 数组大小 ) 的整型数组,数组中的元素一些出现了两次,另一些只出现一次

找到所有在 [1, n] 范围之间没有出现在数组中的数字。

条件:在不使用额外空间且时间复杂度为O(n)的情况下完成这个任务(假定返回的数组不算在额外空间内)

思路分析

解法一:交换数字,再遍历检查

遍历数组,交换数字:将每个数字交换到它理应出现的位置上。

下面情况不用换:

1、当前数字本就出现在理应的位置上;(如 nums[0]=1 )

2、当前数字理应出现的位置上,已经存在一样的数字;(如 nums[0]=1 且 nums[1]=1 说明在 nums[1] 的位置上没有2,缺少这位数字)

遍历检查:如果当前位置没对应正确的数,则将对应缺少的数字加入返回数组。

解法二:将数字指向的下标对应的数字变成负数,(指向两次还是负数),最后遍历数组,正数的下标就说明没有被指向,缺少对应的数字

AC代码

解法一

var findDisappearedNumbers = function (nums) {
    // 定义循环数字和返回数组
    let i = 0;
    let res = [];
    while (i < nums.length) {
        // 跳过情况一:当前数字本就出现在理应的位置上
        if (nums[i] == i + 1) {
            i++;
            continue;
        }
        // 跳过情况二:当前数字理应出现的位置上,已经存在一样的数字
        let tmp = nums[i] - 1;
        if (nums[tmp] == nums[i]) {
            i++;
            continue;
        }
        // 以上两种情况没有就交换到它该在的位置
        [nums[i], nums[tmp]] = [nums[tmp], nums[i]]
    }
    // 返回数组
    for (let i = 0; i < nums.length; i++) {
        if (nums[i] != i + 1) {
            res.push(i + 1)
        }
    }
    return res
};

解法二

var findDisappearedNumbers = function (nums) {
    let len = nums.length;
    for (let i = 0; i < len; i++) {
        //Math.abs()为取得绝对值的方法
        //获得指向的下标
        let tmp = Math.abs(nums[i]) - 1;
        //将指向的下标变为负数
        if (nums[tmp] > 0) {
            nums[tmp] = nums[tmp] * (-1)
        }
    }
    let res = [];
    //遍历得到不被指向的下标,将对应的数字放进数组然后输出
    for (let i = 0; i < len; i++) {
        if (nums[i] > 0) {
            res.push(i + 1)
        }
    }
    return res
};

总结

题目要求不使用额外空间来完成,只能通过修改原数组来完成。通过转移数字或者打标记来解决。

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情