1. 程式人生 > >LeetCode第448題 Find All Numbers Disappeared in an Array解決辦法

LeetCode第448題 Find All Numbers Disappeared in an Array解決辦法

 

 

題目

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)。只使用了恆定的空間。