1.題目描述
在一個長度為n的數組里的所有數字都在0~n-1的范圍內。數組中某些數字是重復的,但是不知道有幾個數字重復了,也不知道每個數字重復了幾次。請找出數組中任意一個重復的數字。例如,如果輸入長度為7,的數組{2,3,1,0,2,5,3},那么對應的輸出是重復的數組2或者3。
2.分析邊界條件及測試用例
1.考慮輸入數組為空,測試用例為{};
2.考慮輸入數組含有大於數組規模的數,測試用例為{0,1,2,3,5};
3.考慮輸入數組不重復,包含兩種可能(都是小於數組規模的數,存在大於數組規模的數(2)
中包含),測試用例為{0,1,2,3,4};
3.三種解法
1.數組排序再掃描
將數組進行排序,從排好序的數組的開頭進行遍歷,記錄當前位置與其之前位置的數,進行比較,若相等則輸出該數,否則判斷下一位數。
1 public static int getRepeatNumber(int[] array) { 2 // Judge the boundary of this problem 3 int len = array.length; 4 if (len == 0) {return -1;} 5 6 // solution 1 sort array then search from first to end 7 Arrays.sort(array); 8 if (array[len - 1] >= len) { 9 return -1; 10 } else { 11 int temp = array[0]; 12 int i = 1; 13 for(; i < len; i++) { 14 if (temp == array[i]) { 15 break; 16 } else { 17 temp = array[i]; 18 } 19 } 20 if (i == len) { 21 return -1; 22 } else { 23 return array[i]; 24 } 25 } 26 }
復雜度分析:時間復雜度O(nlogn),空間復雜度O(1)。
2.哈希表
對數組元素進行遍歷,每次判斷哈希表中是否有該元素,若有,輸出此重復元素,若最后哈希表中元素數量與數組規模相等,表明無重復元素。
1 public static int getRepeatNumber(int[] array) { 2 // Judge the boundary of this problem 3 int len = array.length; 4 if (len == 0) {return -1;} 5 Set<Integer> set = new HashSet<>(); 6 int i = 0; 7 for(; i < len; i++) { 8 if (array[i] >= len) { 9 return -1; 10 } else { 11 if (set.contains(array[i])) { 12 break; 13 } else { 14 set.add(array[i]); 15 } 16 } 17 } 18 if (i == len) { 19 return -1; 20 } else { 21 return array[i]; 22 } 23 }
復雜度分析: 時間復雜度O(n),空間復雜度O(n)。
3.重排數組
從頭到尾依次掃描數組中每一個數字。當掃描到第i個元素時,比較該位置數值m是否等於i。若是,接着掃描下一個數字;否則,將其與第m個數字進行比較。若相等,則返回該重復數字;否則,交換兩個數字,繼續重復前面的過程。
1 public static int getRepeatNumber(int[] array) { 2 // Judge the boundary of this problem 3 int len = array.length; 4 if (len == 0) {return -1;} 5 for(int i = 1; i < len;) { 6 if (array[i] >= len) { 7 return -1; 8 } else { 9 if (array[i] == i) { 10 i++; 11 } else { 12 if (array[i] == array[array[i]]) { 13 return array[i]; 14 } else { 15 int tmp = array[i]; 16 array[i] = array[array[i]]; 17 array[array[i]] = tmp; 18 } 19 } 20 } 21 } 22 return -1; 23 }
復雜度分析: 時間復雜度O(n),空間復雜度O(1)。