最大的K个数
建立最大的k个数,可以通过快速排序来实现,也可以通过堆排序来实现。我们来看堆排序的实现过程。
其中,也是有两种思路:第一种思路是:把数组里的所有的数建堆(O(nlogn)),然后交换k次,通过堆排序实现。(klogn)
时间复杂度是:O((n+k)logn) = O(nlogn)
第二种思路是:先用前面的k个数来建最小堆,堆顶元素将会是这个堆里的最小值,然后从第K+1个数开始和堆顶元素进行比较,若此值比堆顶元素小,则这个数比大的至少有k个元素,这个值肯定不是最大的k个数;若此值比堆顶元素大,则这个数有可能是最大的k个数,调整这个堆即可。最后建立的堆就是所求的最大的k个数,并且堆顶元素就是最大的k个数中的最小值。
时间复杂度是:(O(klogk)+O(n-k)logk) = O(nlogk)
第二种思路的代码:
public int[] heapSort(int[] array,int k){ int length = array.length; for(int i=(k-2/2);i>=0;i--){ //先建立具有K个元素的大顶堆 adjustHeap(array,i,k-1); } for(int i=k;i<array.length;i++){ //比较n-K次 if(array[0]>array[i]) { swap(array,0,i); adjustHeap(array,0,k-1); } } return array; } public void adjustHeap(int[] array,int m,int n){ while(2*m+1<=n){ int p = 2*m+1; if(p<n){ if(array[p]<array[p+1]){ p=p+1; } } if(array[m]<array[p]){ swap(array,m,p); m = p; }else{ break; } } } public void swap(int[] array,int p,int q){ int temp = array[q]; array[q] = array[p]; array[p] = temp; }
第一种思路:先把所有的数建堆,然后再交换。
public static void main(String[] args){ int[] array = {1,2,3,4,5,6,7,8}; int[] result = new lianxi().heapSort(array,4); } public int[] heapSort(int[] array,int k){ int length = array.length; for(int i=(length-2/2);i>=0;i--){ adjustHeap(array,i,length-1); } for(int i=0;i<k;i++){ swap(array,0,length-1-i); adjustHeap(array,0,length-2-i); //此处为length-2-i,因为每次需要调整的堆的长度都减1 System.out.println(array[length-1-i]); } return array; } public void adjustHeap(int[] array,int m,int n){ while(2*m+1<=n){ int p = 2*m+1; if(p<n){ if(array[p]>array[p+1]){ p=p+1; } } if(array[m]>array[p]){ swap(array,m,p); m = p; }else{ break; } } } public void swap(int[] array,int p,int q){ int temp = array[q]; array[q] = array[p]; array[p] = temp; }
在堆排序的基础上进行修改:
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) { ArrayList<Integer> arrayList = new ArrayList<>(); if(input == null || k<=0 || k>input.length) return arrayList; for(int i=0;i<input.length;i++){ buildMinHeap(input,input.length-1-i); swap(input,0,input.length-1-i); } for(int i=0;i<k;i++){ arrayList.add(input[i]); } return arrayList; } public void buildMinHeap(int[] input,int n){ int i; if(n==input.length-1) i=(n-1)/2; else i=0; for(;i>=0;i--){ int p = i; while(p*2+1<=n){ int q = 2*p+1; if(q<n){ if(input[q]<input[q+1]){ q = q+1; } } if(input[p]<input[q]){ int temp = input[q]; input[q] = input[p]; input[p] = temp; p=q; }else{ break; } } } } public void swap(int[] input,int i,int j){ int temp = input[j]; input[j] = input[i]; input[i] = temp; }
先构造一个k个元素的堆,然后再进行比较。
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) { ArrayList<Integer> arrayList = new ArrayList<>(); if(input == null || k<=0 || k>input.length) return arrayList; buildMaxHeap(input,k-1); for(int i=k;i<input.length;i++){ if(input[i]<input[0]){ swap(input,0,i); adjust(input,0,k-1); } } for(int i=0;i<k;i++){ arrayList.add(input[i]); } return arrayList; } public void buildMaxHeap(int[] input,int n){ for(int i= (n-1)/2;i>=0;i--){ int p = i; while(p*2+1<=n){ int q = 2*p+1; if(q<n){ if(input[q]<input[q+1]){ q = q+1; } } if(input[p]<input[q]){ int temp = input[q]; input[q] = input[p]; input[p] = temp; p=q; }else{ break; } } } } public void adjust(int[] input,int m,int n){ while(2*m+1<=n){ int q = 2*m+1; if(q<n){ if(input[q]<input[q+1]){ q = q+1; } } if(input[m]<input[q]){ swap(input,m,q); m = q; }else{ break; } } } public void swap(int[] input,int i,int j){ int temp = input[j]; input[j] = input[i]; input[i] = temp; }