大家都知道快排算法,快速排序算法的應用是非常廣泛的,這里舉出幾個例子,談一談快速排序算法的應用。快速排序的思想不僅用於單純的排序問題,對於很多查找類問題,快排算法能達到最小的時間復雜度,是最優解法之一。
首先先java實現一個快速排序函數:
1 private int partition(int[] arr, int l, int h){ 2 int p = arr[l]; 3 int i=l; int j = h+1; 4 while(true){ 5 while(i!=h && arr[++i]<p); 6 while(j!=l && arr[--j]>p); 7 8 if(i >= j){ 9 swap(arr, i, j); 10 break; 11 } 12 } 13 swap(arr, l, j); 14 return j; 15 }
1. 求一個數組里面最小的k個數
通過調用快速排序的 partition() 方法,會返回一個整數 j ,要讓得 a[l..j-1] 小於等於 a[j],且 a[j+1..h] 大於等於 a[j],此時 a[j] 就是數組的第 j 大元素。可以利用這個特性找出數組的第 K 個元素,這種找第 K 個元素的算法稱為快速選擇算法。這種算法時間復雜度為O(N) + O(1)。使用最小堆求解的話時間復雜度不變。代碼如下:
1 public List<Integer> GetLeastNumbers(int[] nums, int k){ 2 List<Integer> ret = new ArrayList<>(); 3 if(nums.length == 0 || k>nums.length || k<0) 4 return new ArrayList<Integer>(); 5 6 findKthSmallest(nums, k-1); 7 8 for (int i = 0; i < k; i++) 9 ret.add(nums[i]); 10 return ret; 11 } 12 13 private void findKthSmallest(int[] nums, int k) { 14 int l = 0; 15 int h = nums.length-1; 16 17 while(l<h){ 18 int res = partition(nums, l, h); 19 20 if(res == k){ 21 return; 22 23 }else if(res<k){ 24 l= res+1; 25 }else{ 26 h=res-1; 27 } 28 } 29 } 30 31 private int partition(int[] arr, int l, int h){ 32 int p = arr[l]; 33 int i=l; int j = h+1; 34 while(true){ 35 while(i!=h && arr[++i]<p); 36 while(j!=l && arr[--j]>p); 37 38 if(i >= j){ 39 swap(arr, i, j); 40 break; 41 } 42 } 43 swap(arr, l, j); 44 return j; 45 } 46 47 private void swap(int[] arr, int i, int j) { 48 int temp = arr[i]; 49 arr[i] = arr[j]; 50 arr[j] = temp; 51 52 }
2 求數組中出現次數超過一半的數
容易理解次數超過一半的那個數必然是這個數組的中位數,依次可以使用快排來尋找數組的中位數,時間復雜度為O(n),java代碼如下所示
1 public int MoreThanHalfNum(int[] nums){ 2 3 if(nums.length == 0 || nums == null) 4 return 0; 5 6 int ret = 0; 7 int end = nums.length-1; 8 int start = 0; 9 int middle = end/2; 10 11 int index = partition(nums, start, end); 12 13 while(index != middle){ 14 if(index < middle) index=partition(nums, index+1, end); 15 if(index > middle) index=partition(nums, start, index-1); 16 } 17 18 ret = nums[middle]; 19 20 return ret; 21 } 22 23 private int partition(int[] arr, int l, int h){ 24 int p = arr[l]; 25 int i=l; int j = h+1; 26 while(true){ 27 while(i!=h && arr[++i]<p); 28 while(j!=l && arr[--j]>p); 29 30 if(i >= j) 31 break; 32 33 swap(arr, i, j); 34 35 } 36 swap(arr, l, j); 37 return j; 38 } 39 40 private void swap(int[] arr, int i, int j) { 41 int temp = arr[i]; 42 arr[i] = arr[j]; 43 arr[j] = temp; 44 45 }
時間復雜度為o(n)。
