LeetCode第448题 Find All Numbers Disappeared in an Array解决办法

本文介绍了一种在不使用额外空间的情况下,查找数组中缺失数字的方法。该方法利用原数组进行标记,实现O(n)时间复杂度内解决问题。文章对比了三种不同解决方案,并详细分析了其时间与空间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

题目

Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.

Find all the elements of [1, n] inclusive that do not appear in this array.

Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.

Example:


Input: [4,3,2,7,8,2,3,1]

Output: [5,6]


解决办法

这个问题的基本要求是:

1.对于一个给定的数组,大小为n,数组中的元素为1 ≤ a[i] ≤ n ,其中存在部分元素大小相同的情况,要求查找在1~n中有哪些数在数组中不存在。

2.除给定的数组和作为返回值的List外,不在分配额外的存储空间,且时间复杂度为O(n)。(PS.非强制要求)

方法一 [Time Limit Exceeded]

class Solution {
    public List<Integer> findDisappearedNumbers(int[] nums) {
        List<Integer> list = new ArrayList<Integer>();
        for(int i=1;i<=nums.length;i++){
            if(!isExist(i,nums))
                list.add(i);
        }
        return list;
    }
    
    public boolean isExist(int i,int[] nums){
        for(int j=0;j<nums.length;j++){
            if(nums[j]==i)
                return true;
        }
        return false;
    }
}

在这个方法中,我们采用线性搜索算法,这个算法比较简单,通过检查数组中的每个元素,一次一个地按顺序查找并判断特定值是否在列表中,直到找到所需的元素。如果找到一个对应元素,则返回true, 如果没有,就继续执行。在程序结束时返回false。

复杂性分析

  • 时间复杂度: O(n ^ 2)

  • 空间复杂度: O(1)。只使用了恒定的空间。

方法二 [Accepted]

class Solution {
    public List<Integer> findDisappearedNumbers(int[] nums) {
         List<Integer> list = new ArrayList<Integer>();
         Set<Integer> set = new HashSet<Integer>();
         for(int i=1;i<=nums.length;i++){
             set.add(i);
         }
         for(int num:nums){
             set.remove(num);
         }
         list.addAll(set);
         return list;
     }
}

通过将1~n添加到set集合中,然后再将数组中存在的元素从set中remove掉,剩余的元素即1~n中不存在于数组里的数。

复杂性分析

  • 时间复杂度: O(n )

  • 空间复杂度: O(n)。创建Set集合消耗了额外的空间。

方法三 [Accepted]

class Solution {
    public List<Integer> findDisappearedNumbers(int[] nums) {
		List<Integer> res = new ArrayList<Integer>();
		for(int i=0;i!=nums.length;i++){
			nums[Math.abs(nums[i])-1] = -Math.abs(nums[Math.abs(nums[i])-1]);
		}
		for(int i=0;i!=nums.length;i++){
			if(nums[i]>=0){
				res.add(i+1);
			}
		}
		return res;
	}
}

最巧妙的一个算法,通过将数组中指定位置的元素的值取反,最后通过值的正负来判断1~n中有哪些数不存在于数组中。比如nums[1]==4,则将数组中第四个元素取反,即nums[3] = -Math.abs(nums[3])。如果最后数组中nums[5]的值为正,即数组中第六个元素为正,就说明数组中不存在6。

复杂性分析

  • 时间复杂度: O(n)

  • 空间复杂度: O(1)。只使用了恒定的空间。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值