Top K以及java priorityqueue

來源:互聯網
上載者:User

標籤:code   實現   一個   parent   priority   思路   最大   integer   個數   

Top K問題比較常見啦,這裡總結一下方法。

1、用最小堆來做。

思路是先利用數組中前k個數字建一個最小堆,然後將剩餘元素與堆頂元素進行比較,如果某個元素比堆頂元素大,就替換掉堆頂元素,並且重新調整成最小堆。

到這裡,堆中儲存著的其實是前k個最大的數字。堆頂就是第K個最大的數字。這樣前k個,第k個都可以求出來了。代碼如下:

 1     public void find(int[] nums, int k){ 2         PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(); 3         for ( int i = 0 ; i < k ; i ++ ) priorityQueue.offer(nums[i]); 4         for ( int i = k ; i < nums.length ; i ++ ){ 5             if ( nums[i] > priorityQueue.peek() ){ 6                 priorityQueue.poll(); 7                 priorityQueue.offer(nums[i]); 8             } 9         }10         System.out.println(priorityQueue.peek());11         while ( priorityQueue.peek() != null ){12             System.out.print(priorityQueue.poll()+"   ");13         }14     }

輸出第一行是第k大的數,第二行是前k大的數。

現在有兩個思考:1、這個代碼是對重複數字有效,也就是如果輸入是[3,4,5,6,6],求第三大的數字,結果就是5。但是實際上我們是想忽略重複,希望輸出4,應該怎麼辦?2、如果是想求最小的k個數字應該怎麼辦。

如果想忽略重複,我們在建堆和後面元素入堆的過程中增加一個判斷就可以了。

如果想要求前k小或者是d第k小的數字,這裡就要瞭解一下java對堆的封裝類:priorityqueue。這個封裝類預設實現最小堆並且考慮重複。如果想實現上面的思路,就要重寫compare方法。compare方法在siftup的過程中使用到,siftup這個函數就是向上調整,這個函數會比較孩子節點和父親節點的大小關係是否滿足要求,如果滿足,就break;如果不滿足就會交換孩子和父親的值。

 1 private void siftUp(int k, E x) { 2     if (comparator != null) 3         siftUpUsingComparator(k, x); 4     else 5         siftUpComparable(k, x); 6 } 7 private void siftUpUsingComparator(int k, E x) { 8     while (k > 0) { 9         int parent = (k - 1) >>> 1;10         Object e = queue[parent];11         if (comparator.compare(x, (E) e) >= 0)12             break;13         queue[k] = e;14         k = parent;15     }16     queue[k] = x;17 }

注意這裡如果沒有重寫compare方法,就會調用預設的siftupComparable方法(這個方法就是構建最小堆的方法)。如果重寫了,那麼就會使用compare方法中的比較方法來判斷是否滿足條件。我重寫了一個最大堆的代碼如下:

1 PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(new Comparator<Integer>() {2             @Override3             public int compare(Integer o1, Integer o2) {4                 return o2-o1;5             }6         });

compare方法中o1參數是孩子節點,o2參數是父親節點。這裡最大堆的意思就是:如果父親節點的值大於孩子節點的值,就不需要調整;否則交換。所以根據這個原則建立起的堆就是最大堆。

那麼求第k個最小的數,以及前k個最小的數代碼就顯而易見了:

 1     public void find(int[] nums, int k){ 2         PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(new Comparator<Integer>() { 3             @Override 4             public int compare(Integer o1, Integer o2) { 5                 return o2-o1; 6             } 7         }); 8         for ( int i = 0 ; i < k ; i ++ )  9         {10             if ( !priorityQueue.contains(nums[i]) ) priorityQueue.offer(nums[i]);11         }12         for ( int i = k ; i < nums.length  ; i ++ ){13             if ( nums[i] < priorityQueue.peek() && !priorityQueue.contains(nums[i]) ){14                 priorityQueue.poll();15                 priorityQueue.offer(nums[i]);16             }17         }18         System.out.println(priorityQueue.peek());19         while ( priorityQueue.peek() != null ){20             System.out.print(priorityQueue.poll()+"   ");21         }22     }

 

Top K以及java priorityqueue

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.