求N個數中前k個大的數
解題思路:一般思路就是將N個數排序後,取前k個數就ok。但是如果N個數是幾十億個數,載入不到記憶體怎麼辦?這時候就需要利用堆來解決這個問題
具體的思路是:先建一個k個數的小堆,然後從k+1個數往後的值與堆頂元素比較,若此數比堆頂元素大,就將堆頂元素用這個數替換,然後重新調整堆,以此向後重複上述過程,直到將N個數比較完成,那麼此時組成這個堆的k個元素就是前k個大的數。
接下來我們講一下最小堆與最大對堆的思想:
一、堆樹的定義
堆樹的定義如下:
(1)堆樹是一顆完全二叉樹;
(2)堆樹中某個節點的值總是不大於或不小於其孩子節點的值;
(3)堆樹中每個節點的子樹都是堆樹。
當父節點的鍵值總是大於或等於任何一個子節點的鍵值時為最大堆
。 當父節點的鍵值總是小於或等於任何一個子節點的鍵值時為最小堆。如下圖所示,上面的為最大堆,下面的為最小堆。
二、堆樹的操作
以最大堆為例進行講解,最小堆同理。
原始資料為a[] = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7},採用順序儲存方式,對應的完全二叉樹如下圖所示:
(1)構造最大堆
在構造堆的基本思想就是:首先將每個葉子節點視為一個堆,再將每個葉子節點與其父節點一起構造成一個包含更多節點的對。
所以,在構造堆的時候,首先需要找到最後一個節點的父節點,從這個節點開始構造最大堆;直到該節點前面所有分支節點都處理完畢,這樣最大堆就構造完畢了。
假設樹的節點個數為n,以1為下標開始編號,直到n結束。對於節點i,其父節點為i/2;左孩子節點為i*2,右孩子節點為i*2+1。最後一個節點的下標為n,其父節點的下標為n/2。
如下圖所示,最後一個節點為7,其父節點為16,從16這個節點開始構造最大堆;構造完畢之後,轉移到下一個父節點2,直到所有父節點都構造完畢。
最後根據 最大值堆的思想,貼出一份最大堆的實現程式碼:
public class MaxHeap { private int []heap ; private int currentSize; private static int MAXSIZE ; public MaxHeap(int n){ heap=new int[n]; currentSize=0; MAXSIZE=n; } public boolean insert(int x){ if(currentSize==MAXSIZE){ System.out.println("Sorry,this heap is full!"); return false; } //如果堆不滿的話 currentSize++; int flag=currentSize-1; while(flag>0){ int parent=(flag-1)/2; if(heap[parent]>x){ heap[flag]=x; return true; }else{ heap[flag]=heap[parent]; flag=parent; } } heap[0]=x; return true; } public void siftDown(int flag){ int want=flag; int x=heap[flag]; while(want<currentSize){ int lChild=2*want+1; int rChild=2*want+2; int MAXChildNumber; if(lChild>currentSize){ //沒有孩子節點 heap[want]=x; }else{ //有兩個孩子節點 if(lChild<currentSize){ MAXChildNumber=heap[lChild]>heap[rChild]?lChild:rChild; }else{ MAXChildNumber=lChild; } if(heap[MAXChildNumber]<x){ heap[want]=x;return; }else{ heap[want]=heap[MAXChildNumber]; want=MAXChildNumber; } } } } public int deleteTop(){ if(currentSize<0){ System.out.println("Sorry, this heap is empty!"); return -1; } int target=heap[0]; int substitute=heap[currentSize-1]; this.currentSize--; heap[0]=substitute; siftDown(0); return target; } }
public class MaxHeapTest {
public static void main(String []args){
MaxHeap maxHeap=new MaxHeap(7);
for(int i=1;i<=7;i++){
maxHeap.insert(i);
}
for(int i=0;i<7;i++){
System.out.print(maxHeap.deleteTop()+" ");
}
System.out.println("\n");
}
}
執行結果:
相關推薦
求N個數中前k個大的數
解題思路:一般思路就是將N個數排序後,取前k個數就ok。但是如果N個數是幾十億個數,載入不到記憶體怎麼辦?這時候就需要利用堆來解決這個問題具體的思路是:先建一個k個數的小堆,然後從k+1個數往後的值與堆頂元素比較,若此數比堆頂元素大,就將堆頂元素用這個數替換,然後重新調整堆,
面試題: 求N個數中前k個大的數(大資料)
解題思路:一般思路就是將N個數排序後,取前k個數就ok。但是如果N個數是幾十億個數,載入不到記憶體怎麼辦?這就需要另外一種思路了,那就是利用堆。 具體的思路是:先建一個k個數的小堆,然後從k+1個數往
[USACO12FEB]牛的IDCow IDs 一題多解(求二進位制中有k個1 ,第n大的數)
題目: FJ給他的奶牛用二進位制進行編號,每個編號恰好包含K 個"1" (1 <= K <= 10),且必須是1開頭。FJ按升序編號,第一個編號是由K個"1"組成。 請問第N(1 <= N <= 10^7)個編號是什麼。 不同尋常的暴力: 樣例是升序的第7個,我
hdu 3915 Game 求N個數中取若干個數字使得它們的異或值為0的方法數 高斯消元(mod2)
Problem Description Mr.Frost is a child who is too simple, sometimes naive, always plays some simple but interesting games with his fri
分治演算法求N個數中第K小(大)的數
這個學期開演算法課,跟著進度寫寫程式碼就好。這周講分治,說到了求N個數中第K小(大)數的問題,寫寫看。 分治演算法的複雜度是O(n),用到了快速排序的思路:先選取一個參考數進行一次快排,拿升序來說的話,快排之後左邊所有數<參考數,右邊所有數>參考數,然後根據左右
我的第六個C++上機報告(求四個數中的最大數和最小數)
/* * Copyright (c) 2011, 煙臺大學計算機學院 * All rights reserved. * 作 者:王昕彤 * 完成日期:2012 年 10月 11日 * 版 本 號:v1.0 * * 輸入描述:四個數 * 問題描述:給定四個數,求出其中
逆序(n個數中m個逆序)
.com light ostream size 逆序對數 逆序對 std ios pac 逆序對數列 對於一個數列{ai},如果有i<j且ai>aj,那麽我們稱ai與aj為一對逆序對數。若對於任意一個由1~n自然數組成的 數列,可以很容易求出有多少個逆序對數
【單調棧】求一個數組第一個比他小的數的位置
type 技術分享 bit esp alt log lap while play 【AC】 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int
埃氏篩法(求n以內有多少個素數)
cin algorithm memset fin lse mod pre 判斷 end 題目大意:給定整數n,請問n以內有多少個素數 思路:想必要判斷一個數是否是素數,大家都會了,並且可以在O(根號n)的復雜度求出答案,那麽求n以內的素數呢,那樣求就顯得有點復雜了,下面看一
求n個數的排列
如果給定N個不同字元,將這N個字元全排列,最終的結果將會是N!種。如:給定 A、B、C三個不同的字元,則結果為:ABC、ACB、BAC、BCA、CAB、CBA一共3!=3*2=6種情況。 public class Test6 { //設定總數 private static int count =0;pub
演算法 求n個數的中位數 C
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
YTUOJ——函式模板--求n個數的和
題目描述 利用函式模板求4個數的和。 部分程式碼已給定如下,只需要提交缺失的程式碼。 輸入 第一行4個字元 第二行4個整數 第三行4個小數 輸出 第一行4個字元ascii的和 第二行4個整數的和 第三行4個小數的和 樣例輸入 abcd 1 2 3 4 1.1 2.2
求兩個數哪兩個最接近c++程式碼
int main() { int a[MAXN]; int i = 0; int minus =0, abso = 0; int n1 = 0, n2 = 1; while (scanf_s(“%d”, &
求n個數的最小公倍數
騰訊2018秋招筆試題(研發類),程式設計題第一題: 輸入:n m為離n最近的整數,且m要滿足: {n+1,n+2,...,m}的最小公倍數和{1,2,3,...,m}的最小公倍數相同。 輸出:m import java.util.Arrays; import ja
求若干個數裡的最大數!!!
執行環境:win10 vs2013 題目一:求10 個整數中最大值。 這個問題我們可以才用陣列來解決問題,10個數我們需要定義一個長度為10的陣列,由於賦給的值是整數,因此陣列可以
C/C++ 求三個數中的最大數(簡單方法,一步到位)
#include <iostream> using namespace std; int max_3(int a, int b, int c) { return a > b ? (
演算法 - 求n個數的中位數(C++)
//**************************************************************************************************** // // 求n個數的中位數 - C++ - by Chimomo // //
求N個數的階乘相乘素因子個數總和
#include <bits/stdc++.h> using namespace std; bool vis[10000004]; vector<long long>prim; long long maxprim[10000004];//最大素因子 long long num
C語言求10個數中的最大數
#include <stdio.h> int main() { int max; int a[10]={1,20,3,4,5,6,7,8,9,10}; max=a[0]; for(int i=1;i<10;i++) { &
求三個數中的最大數
找最大數 任意輸入三個整型的數,找出其中最大的數,並輸出 輸入: 3 8 6 輸出: 8 #include <stdio.h> #include <stdlib.h>