這個題目應該是一些大公司面試題中常常被問到的,這裏我給出一種作法,至於面試官滿不滿意我就不知道了。咱們知道,這種找出前多少個最大或者最小的最適合用堆排序(對堆排序不熟悉的讀者能夠參考爲的這篇博客:堆排序)。可是若是咱們用1億個數去建堆並調整,固然時間複雜度是不容許的。題目中要求前100個大的,那麼咱們就只用100個數建堆,並且是創建成最小堆。剩下的1億減100個數依次和堆頂元素比較,若是比堆頂元素小,那麼無論它。若是比堆頂元素大,就用這個元素把堆頂元素替換掉,而後調整堆,繼續保持最小堆的性質。直到剩下的全部元素都和堆頂元素比較完畢。那麼堆中的100個數就是最大的。假設一共是n個數,找前m個大的。第一次建堆並調整的時間大約爲mlog(m),那麼對於剩下的每一個元素,最壞的狀況下就是每一個都調整堆,堆調整一次的時間複雜度爲log(m),因此總的時間複雜度爲(n-m)log(m) + mlog(m) = nlog(m)html
public class Demo { public static void main(String[] args) { int n = 10000; int m = 10; int[] arr = new int[n]; for(int i = 0; i < n; i++) { arr[i] = i + 1; } print(arr,n); for(int i = 0; i < m; i++) { System.out.print(arr[i] + " "); } } //剩下的n-m個數與堆頂元素依次比較,並調整堆結構 public static void print(int[] arr, int m) { //把前m個數建成最小堆 createSmallHeap(arr,m); //把剩下的arr.length-m個數字依次與最小堆的堆頂元素比較 //若是比堆頂元素大,那麼就替換爲堆頂,而後對堆頂進行調整。 //當全部的元素遍歷一遍後,堆中元素就是前m個最大的。 for(int i = m; i < arr.length; i++) { if(arr[i] > arr[0]) { arr[0] = arr[i]; adjustHeap(arr,m,0); } } } //新建堆 public static void createSmallHeap(int[] arr, int m) { for(int i = m / 2 - 1; i >= 0; i--) { adjustHeap(arr, m, i); } } //調整爲最小堆 public static void adjustHeap(int[] arr, int m, int i) { int temp = arr[i]; for(int k = 2 * i + 1; k < m; k = 2 * k + 1) { if(k + 1 < m && arr[k + 1] < arr[k]) k++; if(temp > arr[k]) { arr[i] = arr[k]; i = k; } } arr[i] = temp; } }