Leetcode 雙堆實現排序

2021-10-10 15:12:30 字數 1984 閱讀 4725

雙堆,乙個最大堆,乙個最小堆通常用於實現某種排序查詢策略,可以維護在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

輸出:

11

思路傳統的思路是基於排序,按照利潤從小到大排序,每次從最大收益開始,找到乙個收益最大並且開銷小於w的專案執行,並增加收益w,直到做完k次或者不能執行(沒有乙個能做的專案)

複雜度: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最大的了,不用處理,如果...