Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once. Find all the elements that appear twice in this array. Could you do it without extra space and in O(n) runtime? Example: Input: [4,3,2,7,8,2,3,1] Output: [2,3]
存在一個整數數組,其中的全部元素都位於1~n之間,其中n是數組的長度。有的元素出現了一次,而有的元素出現了兩次。找到數組中全部出現兩次的數字。java
爲了在O(N)的時間內找到全部的出現兩次的數字,其核心要求在於用現有的數組記錄已經訪問過的元素,同時不會丟失還沒有訪問過的元素。思路一採用交換的核心思想,即每次都將當前下標上的值和以該值爲下標的位置上的值進行交換,若是該值下標位置上的值和其相等,則說明該數字已經被遍歷過一遍了。數組
代碼以下:app
public List<Integer> findDuplicates(int[] nums) { int index = 0; List<Integer> result = new ArrayList<Integer>(); while(index < nums.length) { int num = nums[index]; if(num == 0){ index++; }else if (nums[num-1] == num) { if(index != num-1){ result.add(num); nums[index] = 0; } index++; }else{ swap(index, num-1, nums); } } return result; } public void swap(int i, int j, int[] nums) { int tmp = nums[i]; nums[i] = nums[j]; nums[j] = tmp; }
有沒有一種辦法在既保留當前位置上的值nums[i]的同時,又可以用某種方式記錄i+1是否已經被訪問過了?能夠經過取反的方法來記錄是否被訪問過這個狀況。若是訪問到下標爲i的位置上的值,則去判斷nums[nums[i]-1]位置上的值是否爲負數,若是是,則說明num[i]出現了兩次,不然將nums[nums[i]-1]位置上的值取反保留。this
代碼以下:spa
public List<Integer> findDuplicates(int[] nums) { List<Integer> res = new ArrayList<>(); for (int i = 0; i < nums.length; ++i) { int index = Math.abs(nums[i])-1; if (nums[index] < 0) res.add(Math.abs(index+1)); nums[index] = -nums[index]; } return res; }