LeetCode刷题笔记-简单-448-找到所有数组中消失的数字

找到所有数组中消失的数字

1、题目描述

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

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

您能在不使用额外空间且时间复杂度为O(n)的情况下完成这个任务吗? 你可以假定返回的数组不算在额外空间内。

示例:

输入: [4,3,2,7,8,2,3,1]

输出: [5,6]

2、解题思路

注意题目要求不能使用额外空间,这也是这道题的难点所在(如果没有不能使用额外空间这个要求的话,直接创建一个数组int hash[26] = {0}; for(int i=0;i<nums.size();i++){hash[nums[i]-1] += 1;}找hash中为0的就是缺少的)。这道题里面其实包含了隐藏的条件,1<= nums[i] <= n,即每个数字本身都对应一个0<= i <= n-1的数组下标。我们可以利用数组内容本身跟数字下标的关联找出缺失的数字。扫描两遍数组,第一次将所有数字做标记,第二次根据标记信息找出缺失的数字。
假设有数组[1,2,3,4,5,6]如下图:

在这里插入图片描述
数组上方的是数组的下标,通过这张图可以发现,数组中的每个值都有一个对应的数组下标,比如值为4的对应下标3。即值为i对应下标i-1
如果数组是乱序的呢?
在这里插入图片描述

乱序的数组并不影响,比如值为3的对应的是下标2,值为6的对应的是下标5。

我们可以利用下标这个隐藏条件,再假设有下面数组,数组缺少5
在这里插入图片描述
因为每个值为i的都对应下标i-1,我们将值为i对应的下标i-1中的数组值nums[i-1]置为负,比如值是3的对应下标2,我们将nums[2]中的值设置为-abs(nums[2])(abs代表取绝对值)。
对[1,2,3,4,6,6]这个数组我们做如下操作:
值1对应下标0,将nums[0]中的值设置成 -abs(nums[0]),即-1
值2对应下标1,将nums[1]中的值设置成 -abs(nums[1]),即-2
值3对应下标2,将nums[2]中的值设置成-abs(nums[2]),即-3
值4对应下标3,将nums[3]中的值设置成-abs(nums[3]),即-4
值6对应下标5,将nums[5]中的值设置成-abs(nums[5]),即-6
值6对应下标5,将nums[5]中的值设置成-abs(nums[5]),即-6
在这里插入图片描述
再扫描一遍数组nums:
1、找到大于0的值值是多少不重要重要的是值的下标i
2、对下标进行操作,i+1就是我们要找的缺少的数字。
例如:数组nums中大于0的值是6,它的数组下标是4,说明缺少数字5。
可以反向思考:假如存在数字5,那么它对应的下标就是4,根据上面的操作(值5对应下标4,将nums[4]中的值设置成-abs(nums[4]),即为负数),那么下标为4的nums[4]的值就不可能大于0,所以不存在数字5。

如果数组是乱序的,也不会影响其结果。
扫描一遍:
对[2,6,6,1,3,4]这个数组我们做如下操作:
值2对应下标1,将nums[1]中的值设置成 -abs(nums[1]),即-6
值6对应下标5,将nums[5]中的值设置成-abs(nums[5]),即-4
值6对应下标5,将nums[5]中的值设置成-abs(nums[5]),即-4
值1对应下标0,将nums[0]中的值设置成 -abs(nums[0]),即-2
值3对应下标2,将nums[2]中的值设置成-abs(nums[2]),即-6
值4对应下标3,将nums[3]中的值设置成-abs(nums[3]),即-1
在这里插入图片描述
数组nums中大于0的值是3(验证上面提到的值不同要,重要的是对应的下标),它的数组下标是4,说明缺少数字5。

再看下题目中的列子,数组[4,3,2,7,8,2,3,1]对应下标i值[3,2,1,6,7,1,2,0],将num[3],num[2],num[1],num[6],num[7],num[0]置为负,得到新数组[-4, -3, -2, -7, 8, 2, -3, -1]
在这里插入图片描述
扫描一遍8和2大于0,他们分别对应下标4和下标5,所以缺失的数字是5和6。

复杂度分析
时间复杂度:O(n),扫描两边数组
空间复杂度:O(1),因为我们在原地修改数组,没有使用额外的空间。

3、代码

class Solution {
public:
    vector<int> findDisappearedNumbers(vector<int>& nums) {
        for(int i=0;i<nums.size();i++) 
        {
		     nums[abs(nums[i])-1] = -abs(nums[abs(nums[i])-1]);//abs表示取绝对值
		}
		vector<int> res;
		for(int i=0;i<nums.size();i++) 
        {
			if(nums[i]>0)
				res.push_back(i+1);
		}
		return res;

    }
};

官方解答

本文参考-多图演示 448.找到所有数组中消失的数字

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值