請求出一組序列中的數中的前k小的數,或者前k大的數,問題很簡單
該題利用順序儲存二叉堆可以很好的解決:
首先我們先解釋一下「堆」這個資料結構
堆這個東西我們可以理解成是利用了二叉樹的一條性質而人工構建的一組順序儲存二叉樹
分類:最小堆:每個父親節點都比子節點小
最大堆:每個父親節點都比子節點大
順序儲存實現的原理:
二叉樹存在一條性質,(這個性質和二叉樹的層序遍歷的序號有關 )
n號節點的左兒子的存在的話編號為2*n,右兒子存在的話,編號為2*n+1
那麼我們依據這一條就可以完全實現二叉樹的線性儲存,並且這種結構和性質還可以方便我們進行各種操作
下面主要來介紹二叉堆的核心的兩個函式:向上浮動調整和向下浮動調整——目的是用來維護我們最小堆和最大堆的性質
《以求前k小的數來舉例》
說到這裡,有的人可能會問了,為什麼我們用最小堆或者最大堆可以解決這個問題呢
我們來這麼考慮,我們如果可以構建出只有k個元素的 最大堆
每次加入新的元素,我們將該元素和堆頂進行比較,如果比堆頂小的話,我們將其和堆頂進行替換,然後再次進行調整維護,直到所有的資料都加入完畢,那麼堆裡面剩下的就是所有的我們要求的元素,這時候我們再利用最小堆的維護函式進行調整進行堆排序就可以按順序輸出前k個元素了
原理講完了,那麼這個核心的向上調整函式和鄉下調整函式到底怎麼實現呢
在**段中進行解析:
void siftdown(int i) //i代表要開始維護的節點的層序標號
2.逐個插入不斷維護:
void buildheap(int num)
}
基於上面的原理我們可以很好地實現查詢前k個數的操作,但是至於堆排序我們還沒有進行講解
其是堆排序很簡單
按照公升序排列我們需要最大堆,按照降序排列我們需要最小堆
每次我們將堆尾和堆頂進行交換,然後將堆數遞減,保持堆尾固定,然後在向下調整,重複過程,直到我們的堆數為1,然後這個堆就有序了
所以說根據上面的原理講解我們很容易發現堆排序的複雜度始終是o(n*logn)的logn是指堆的二叉樹深度,n是因為我們每次都要從未到頭進行遍歷交換
不多說了,附上**:
void heapsort(int num) //堆的大小
}
微軟面試百題007 鍊錶相交
給出倆個單向鍊錶的頭指標,比如h1,h2,判斷這倆個鍊錶是否相交。為了簡化問題,我們假設倆個鍊錶均不帶環。問題擴充套件 1.如何判斷鍊錶存在環 2.如果需要求出倆個鍊錶相交的第乙個節點列?1.如何判斷鍊錶帶環 我們加入兩個指標,乙個快指標,乙個慢指標,快指標一次前進2個單位,慢指標一次前進乙個單位 ...
微軟面試百題009 按詞反轉句子
翻轉句子中單詞的順序。題目 輸入乙個英文句子,翻轉句子中單詞的順序,但單詞內字元的順序不變。句子中單詞以空格符隔開。為簡單起見,標點符號和普通字母一樣處理。例如輸入 i am a student.則輸出 student.a am i 棧 我們先將句子的內容儲存下來,然後開闢乙個棧,以單詞為單位不斷的...
面試智力題 賽馬問題求前幾名
25個人,每5個人乙個跑道,最少經過幾次比賽,得到前三名 第一步 25個人分成5組,每組5人,分別比賽,得出每組的第一名,並對第一名進行排序,為a1,b1,c1,d1,e1 第二步 a1,b1,c1,d1,e1進行一次比賽,得出第一名,假設為a1,此時經過6輪比賽,得出第一名 第三步 找第二名第三名...