雙堆,乙個最大堆,乙個最小堆通常用於實現某種排序查詢策略,可以維護在o(nlogn)的時間複雜度。典型的例子是實現輸入流的中位數快速查詢,其可以在o(1)的時間內返回中位數。基本思路是,維護兩個大小相等(或相差不超過1的堆每次新來的數字判斷其與最大堆的堆頂(較小那一部分集合的最大值)大小,來決定加入到哪一部分,並合適的移動,使得兩邊維護者數量相等的部分。
題目描述
給定兩個整數w和k,w代表你擁有的初始資金,k代表你最多可以做k個專案。再給定兩個長度為n的正數陣列costs和profits,代表一共有n個專案,costs[i]和profits[i]分別表示第i號專案的啟動資金與做完後的利潤(注意是利潤,如果乙個專案的啟動資金為10,利潤為4,代表該專案最終的收入為14)。你不能並行只能序列地做專案,並且手裡擁有的資金大於或等於某個專案的啟動資金時,你才能做這個專案。該如何選擇做專案,能讓你最終的收益最大?返回最後能獲得的最大資金
[要求]
時間複雜度為o(k \log n)o(klogn),空間複雜度為o(n)o(n)
輸入:4 3 2
5 4 1 2
3 5 3 2
輸出:思路傳統的思路是基於排序,按照利潤從小到大排序,每次從最大收益開始,找到乙個收益最大並且開銷小於w的專案執行,並增加收益w,直到做完k次或者不能執行(沒有乙個能做的專案)11
複雜度:o(n2)
維護乙個cost的最小堆,初始化:所有專案;
乙個表示當前可做專案的收益的最大堆max_profit,初始化:將min_cost中所有小於等於w的專案存入最大堆中。(不斷彈出堆)
開始乙個迴圈:①每次從最大堆中執行乙個專案(可做並且收益最大),增加w
②同時從min_cost最小堆中不斷彈出小於等於w專案 =》壓入最大堆max_profile
迴圈結束條件:專案完成數量==k 或 沒有任何乙個可做專案
**實現
//仿函式 比較器 實現priority_queue
struct cmp};
struct cmp2};
intmain()
priority_queue
int,
int>
,vector
int,
int>>
,cmp2> max_profit;
//收益最大堆(維持能夠執行的專案)
while
(!min_cost.
empty()
&& min_cost.
top(
).first<=w)
//先將那些能夠cost的壓入 max_profit
int count=0;
//雖然為內外兩個while迴圈 但本質是兩個堆之間轉移 : 最多轉移n個 nlog(n)
while
(count
empty()
==false
) count++
;//執行的專案增加
} cout<
}
每次堆的調整複雜度為o(logn) 調整n次,總的時間複雜度為:o(nlogn)堆以及堆排序實現
1.今天實現了一下堆排序,這裡的堆是指二叉堆,至於二項堆和斐波那契堆以後再說。先看二叉堆的定義 二叉堆是完全二叉樹或近似完全二叉樹。滿足特性是 父親節點的值大於等於 小於等於 左右孩子的值,並且左右子樹也是二叉堆。對應的二叉堆是大頂堆 小頂堆 二叉堆是完全二叉樹,可以用線性表來儲存。2.實現堆排序時...
堆的性質 堆的實現 堆排序
目錄 一 堆的性質 二 堆的實現 1.儲存方式 2.向堆中插入元素 3.刪除堆頂元素 4.其他操作 5.完整 三 堆排序 1.原地建堆 2.排序 3.完整 4.建堆的複雜度 o n 5.堆排序的複雜度 o nlogn 6.和快速排序的比較 堆是一種特殊的樹。只要滿足以下兩點,它就是乙個堆 第一點,堆...
leetcode 347 堆排序練習
vectortopkfrequent vector nums,int k else vectorres while q.empty reverse res.begin res.end return res 使用小頂堆,比較的時候,如果比堆頂最小的元素還小,那麼肯定不是topk最大的了,不用處理,如果...