演算法12--topK求一個數組中第k大的數
阿新 • • 發佈:2019-01-01
求一個數組中第k大的值
解法一:
建立一個k個元素的最大堆,首先將陣列中前k個元素放入堆中,此時堆頂元素為第k大的元素,後面繼續遍歷陣列,比較堆頂元素與陣列中元素值,當陣列中元素小於堆頂元素時,將堆頂元素彈出,新元素入堆,這樣最終堆頂元素即為第k大。
可以直接利用Java中優先順序佇列,這裡傳入一個比較器來構造最大堆。
public static int topK3(int[] arr, int k){ PriorityQueue<Integer> q = new PriorityQueue<>(k, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return o2-o1; } }); for(int i=0; i<k; i++){ q.add(arr[i]); } for(int i=k; i<arr.length; i++){ if(arr[i]<q.peek()){ q.poll(); q.add(arr[i]); } } return q.peek(); }
解法二:
利用快速排序中partition函式,當partition返回元素座標q==k-1時,說明q前面已經有k-1個元素比q位置元素小,則arr[q]即為第k大元素。如果q>k-1 說明第k大元素在前半部分,否則在後半部分。
public static int topK(int[] arr, int k, int lo, int hi){ int q = partition(arr, lo, hi); //q==k-1時,arr[q]本身是第K大 if(q==k-1) return arr[q]; else if(q>k-1) return topK(arr, k, lo, q-1); else return topK(arr, q-k, q+1, hi); } public static int topK2(int[] arr, int k){ int lo = 0; int hi = arr.length-1; int q = partition(arr, lo, hi); while(q!=k-1){ if(q>k-1) q = partition(arr, lo, q-1); else q = partition(arr, q+1, hi); } return arr[q]; } public static int partition(int[] arr, int lo, int hi){ int r = arr[hi]; int i = lo - 1; for(int j=lo; j<hi; j++){ if(arr[j]<r){ i++; swap(arr, i, j); } } swap(arr, i+1, hi); return i+1; } private static void swap(int[] arr, int i, int j) { int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; }