题目描述
给定一个范围在 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 春招闯关活动」, 点击查看 活动详情