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]
第一种方法是不符合题目的要求,因为使用了额外的空间,扫描数组a,如果当前位置的数没有出现重复(通过set来判断)则把这个数插入到set里面,否则当前数重复,把当前数插入到List
ans中。
1 class Solution { 2 public List<Integer> findDuplicates(int[] nums) { 3 Set<Integer> set = new HashSet<>(); 4 List<Integer> ans = new ArrayList<>(); 5 int n = nums.length; 6 for (int i = 0; i < n; ++i) { 7 if (set.contains(nums[i])) { 8 ans.add(nums[i]); 9 10 } else { 11 set.add(nums[i]); 12 } 13 } 14 return ans; 15 } 16 }
第二种方法:
注意到1 <= a[i] <= n, 假设不出现重复,则数组a的排列将会是1, 2, 3, ... ,n, 设初始位置i为0, 若a[i] != i + 1 (即a[i]没有在排序后应在的位置)且a[i] != a[ a[i] - 1], 则把a[i] 与a[ a[i] - 1] 交换,i不变,否则 如果 a[i] == a[ a[i] - 1] 则出现了重复的数字,插入该数字到列表ans中,继续往后扫描, 如果a[i] != i + 1 继续往后扫描,即i往后一位,
1 class Solution { 2 public void swap(int []nums, int i, int j) { 3 int temp = nums[i]; 4 nums[i] = nums[j]; 5 nums[j] = temp; 6 } 7 public List<Integer> findDuplicates(int[] nums) { 8 9 List<Integer> ans = new ArrayList<>(); 10 int n = nums.length; 11 int i = 0; 12 while (i < n) { 13 if (nums[i] != nums[nums[i] - 1]) { 14 swap(nums, i, nums[i] - 1); 15 } else { 16 i++; 17 } 18 } 19 20 for (i = 0; i < n; ++i) { 21 if (i != nums[i] - 1) { 22 ans.add(nums[i]); 23 } 24 } 25 return ans; 26 } 27 }