力扣 #287尋找重複數
阿新 • • 發佈:2020-12-03
1 public int findDuplicate(int[] nums) { 2 Arrays.sort(nums); 3 for (int i = 0; i < nums.length - 1; i++) { 4 if (nums[i] == nums[i + 1]) { 5 return nums[i]; 6 } 7 } 8 return -1; 9 }
方法一 排序後對比後一個 沒技術含量 不解釋了
1 class Solution { 2 public int findDuplicate(int[] nums) { 3 Set<Integer> set = new HashSet<>(); 4 for(int i = 0; i < nums.length; i++){ 5 if(set.contains(nums[i])){ 6 return nums[i]; 7 } 8 set.add(nums[i]); 9 } 10 return 0; 11 } 12 }
方法二 HashSet 時間複雜度應該是O(N)吧
1 class Solution { 2 public int findDuplicate(int[] nums) { 3 int n = nums.length - 1; 4 int low = 1; 5 int high = n; 6 while (low < high) { 7 int mid = (low + high) >>> 1; 8 int count = 0; 9 for (int i = 0; i < nums.length; i++) {10 if (nums[i] <= mid) { 11 count++; 12 } 13 } 14 if (count > mid) { 15 high = mid; 16 } else { 17 low = mid + 1; 18 } 19 } 20 return low; 21 } 22 }
進階的二分查找了 例子:[2, 4, 5, 2, 3, 1, 6, 7] 時間複雜度O(NlogN)
第一次查詢count = 5 mid = 4 count > mid 說明 數字[1, 2, 3, 4]中有一個出現重複了 縮小搜尋區間 high = mid
第二次查詢count = 3 mid = 2 count > mid 說明 數字[1, 2]中有一個出現重複了 繼續縮小區間 high = mid
第三次查詢 count = 1 mid = 1 說明區間[1]沒有重複 low = mid + 1 = high 跳出
關鍵在於為什麼 是left < right 跳出而不是之前所說的left <= right
left < right表示在退出迴圈的時候 區間裡只有 1 個數 這個數有可能就是我們要找的數 left <= right表示在區間裡只剩下一個數的時候 還需要繼續查詢