给你一个含 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]
提示:
n == nums.length
1 <= n <= 105
1 <= nums[i] <= n
进阶:你能在不使用额外空间且时间复杂度为 O(n)
的情况下解决这个问题吗? 你可以假定返回的数组不算在额外空间内。
引入hashmap,记录在数组nums中出现的数值,再通过检索hashmap就可以找到哪些是在hashmap中没有出现的。把没有的放进list。不过使用hashmap就不符合进阶要求中的“不使用额外空间”这一条。
- public List
findDisappearedNumbers(int[] nums) { - HashMap
hash = new HashMap<>(); - for (int i = 0; i < nums.length; i++) {
- hash.put(nums[i],true);
- }
- List
list = new LinkedList<>(); - for (int i = 1; i <= nums.length ; i++) {
- if(!hash.containsKey(i)){
- list.add(i);
- }
- }
- return list;
- }
由于数字范围均在[1,n]中,可以用一个长度为你的数组来代替哈希表。利用区间之外的数字来记录数组元素,比如都加某个值,或者把数组元素都变成负的。就是下面的解法2和3。
例:数组[4,3,2,7,8,2,3,1]
将这些整数作为数组下标,将对应的数组置为负值,找遍历完后是正数的。
从第0个元素开始,4-1=3,则把下标为3的数的值,即7变为负,即改为-7
第1个元素,3-1=2,则把下标为2的数的值,即2变为负,即改为-2
第2个元素,-2-1=-3,则把下标为-3的数的值,即下标为5的数变为负,即-2
第3个元素,-7-1=-8,则把下标为0的数的值改为负,即-4
第4个元素,8-1=7,则把下标为7的元素改为负,即-1
第5个元素,-2-1=-3,则把下标为-3的元素改为负,即2
第6个元素,3-1=2,则把下标为2的元素改为负,即-2
第7个元素,-1-1=-2,则把下标为-2的元素改为负,即下标为6的元素改为负,即-3
遍历完数组后我们发现,数组变成了[-4,-3,-2,-7,8,2,-3,-1],则只有下标为4和5的数没有变成负数,则缺失的就是4+1=5,以及5+1=6。
又比如数组中没有消失的数字,[3,2,1,4,5]
第0个元素,3-1=2,则下标为2的元素改为负,即1变成-1
第1个元素,2-1=1,则下标为1的元素改为负,即2变成-2
第2个元素,-1-1=-2,则下标为3的元素改为负,即4变成-4
第3个元素,-4-1=-5,则下标为0的元素改为负,即3变成-3
第4个元素,5-1=4,则下标为4的元素改为负,即5变成-5
遍历完数组后我们发现,数组中所有元素都变成负数了,则没有缺失的数字。
- public List
findDisappearedNumbers(int[] nums) { - List
results = new ArrayList<>(); - for(int i = 0 ; i< nums.length;i++)
- {
- if(nums[Math.abs(nums[i])-1]>0)
- {
- nums[Math.abs(nums[i])-1] = -nums[Math.abs(nums[i])-1];
- }
- }
- for(int i =0;i
- {
- if(nums[i]>0)
- {
- results.add(i+1);
- }
- }
- return results;
- }
或者
- public List
findDisappearedNumbers(int[] nums) { - //用来存放结果
- List
res = new ArrayList<>(); - //1. 遍历下数组的元素,对对应的索引位置的元素作标记
- int len = nums.length;
- for(int i = 0; i < len; i++){
- int num = Math.abs(nums[i]); //由于数组的元素有可能被*-1,所以取绝对值
- int index = num - 1;
- if(nums[index] > 0){
- nums[index] *= -1;
- }
- }
- // 寻找没有标记的索引位置
- for(int i = 0; i < len; i++){
- if(nums[i] > 0){
- int num = i + 1; //将索引转化为对应的元素
- res.add(num);
- }
- }
- return res;
- }
解法3:加数字法
加数字的话要注意,加完后的数不能在原始数组中出现过。由于数组区间是1到n,则加n,加完后最小的也是n+1。将原数组当成哈希表,用每个数对长度n取余,取余后的数一定都小于n,再将这个数加n,遍历数组,当数组中的数小于n时说明数缺失了。
- public List
findDisappearedNumbers(int[] nums) { - int n=nums.length;
- for(int num : nums){
- int x=(num-1)%n;//对n取模来还原它本来的值
- nums[x]+=n;
- }
- List
result=new ArrayList(); - for(int i=0;i
- if(nums[i]<=n){
- result.add(i+1);
- }
- }
- return result;
- }
加油加油^_^
-
相关阅读:
Oracle 中文排序 Oracle 中文字段排序
windows onlyoffice教程
动态新增、修改Logback的Appender(可实现动态调整日志级别,Appender参数)
2022年首家民营征信机构浙江同信获企业征信备案公示
.Net中跨域问题
善用浏览器的一些调试技巧
【PyTorch】PyTorch基础知识——张量
笔记53:torch.nn.rnn() 函数详解
【网页设计】HTML做一个属于我的音乐页面(纯html代码)
2022年湖北武汉安全员ABC考试题库有吗?甘建二
-
原文地址:https://blog.csdn.net/nameofworld/article/details/132691479