1. 程式人生 > >442. Find All Duplicates in an Array 題解

442. Find All Duplicates in an Array 題解

題意:給定一組整數,共n個,這組數字的值均不超過n。在這組數字中,有些數字出現了兩次而其他數字只出現了一次,要求找出該組數字中所有出現兩次的數。並且不能開闢額外的空間,且時間複雜度應為O(n)。

思路:題目不允許開闢額外空間,第一反應是能不能使用位運算/異或來解決該問題,仔細思考後發現似乎行不通。實際上該題目使用的是“藉助陣列下標記錄一些資訊”的思想,題目中“這組數字的值均不超過n”也印證了該想法。總之,該題目的解法是“對於數字n+1,使用下標n處數值的正負進行標記。即使用下標n處數字的正負,來標識數字n+1是否出現過”。

舉例來說,可以使用陣列下標2 處所儲存的數值正負來標識數字3是否已經出現過。當數字3第一次出現時,將下標2處所儲存的數值設定為負。這樣在後續過程中,若數字下標2處的數字為正數,表示3這個數字尚未出現過;若數字下標2處的數字為負數,表示3這個數字已經出現過一次。

本題java程式碼如下:

class Solution {
	public List<Integer> findDuplicates(int[] nums) {
		List<Integer> result = new ArrayList<Integer>();
		for (int i = 0; i < nums.length; i++) {
			int currentNum = Math.abs(nums[i]);
			// 在當前數字對應的下標(當前數字-1)處,使用正負進行標記
			// 例如,使用陣列下標2 處所儲存的數值正負來標識數字3是否已經出現過;
			// 若數字下標2處的數字為正數,表示3這個數字尚未出現過;
			// 若數字下標2處的數字為負數,表示3這個數字已經出現過一次。
			int targetNum = nums[currentNum - 1];
			if (targetNum < 0) {
				result.add(currentNum);
			} else {
				nums[currentNum - 1] = -targetNum;
			}
		}
		return result;
	}
}