浅谈快速排序的二三应用

大家都知道快排算法,快速排序算法的应用是非常广泛的,这里举出几个例子,谈一谈快速排序算法的应用。快速排序的思想不仅用于单纯的排序问题,对于很多查找类问题,快排算法能达到最小的时间复杂度,是最优解法之一。

首先先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)。

永远不要忘记过去,永远不要放弃未来。
原文地址:https://www.cnblogs.com/bravecode/p/10486044.html