LeetCode502---IPO

題目描述

假設 力扣(LeetCode)即將開始其 IPO。爲了以更高的價格將股票賣給風險投資公司,力扣 希望在 IPO 之前開展一些項目以增加其資本。 由於資源有限,它只能在 IPO 之前完成最多 k 個不同的項目。幫助 力扣 設計完成最多 k 個不同項目後得到最大總資本的方式。

給定若干個項目。對於每個項目 i,它都有一個純利潤 Pi,並且需要最小的資本 Ci 來啓動相應的項目。最初,你有 W 資本。當你完成一個項目時,你將獲得純利潤,且利潤將被添加到你的總資本中。

總而言之,從給定項目中選擇最多 k 個不同項目的列表,以最大化最終資本,並輸出最終可獲得的最多資本。

樣例:

輸入: k=2, W=0, Profits=[1,2,3], Capital=[0,1,1].

輸出: 4

解釋:
由於你的初始資本爲 0,你儘可以從 0 號項目開始。
在完成後,你將獲得 1 的利潤,你的總資本將變爲 1。
此時你可以選擇開始 1 號或 2 號項目。
由於你最多可以選擇兩個項目,所以你需要完成 2 號項目以獲得最大的資本。
因此,輸出最後最大化的資本,爲 0 + 1 + 3 = 4

解題思路:
1、定義一個結構體,用來表示資本和利潤
2、按照資本大小建立小根堆,即資本數額小的爲堆頂
3、只要當前堆頂的金額比初始金額小或者等於,就彈出堆頂,
4、將彈出的堆頂元素加入大根堆(是按照利潤大小建立,即利潤大的元素在堆頂)。
5、此時,大根堆的堆頂,即爲當前金額所獲最大利潤
6、考慮邊界問題,最多完成K次項目,大根堆爲空,小根堆的堆頂元素大於原始金額W。

注意:

優先隊列和排序的規則剛好相反:

若排序是從小到大排序,則爲大頂堆
若排序是從大到小排序,則爲小頂堆
C++ STL庫中的sort函數是從小到大排序
而priority_queue隊列是按照大頂堆來實現的。

下面爲AC代碼:

//結點
struct capital_node 
{
	int capital;
	int profits;
	capital_node(int capital, int profits) {
		this->capital = capital;
		this->profits = profits;
	}
};

//比較策略
struct minCapitalCompare//根據花費金額大小比較
{
	bool operator() (const capital_node node1, const capital_node node2) const {//構造小頂堆
		return node1.capital > node2.capital;
	}
};
struct maxProfitCompare//根據利潤大小比較
{
	bool operator() (const capital_node node1, const capital_node node2) const {//構造大頂堆
		return node1.profits < node2.profits;
	}
};

int findMaximizedCapital(int k, int W, vector<int>& Profits, vector<int>& Capital) {
	priority_queue<capital_node, vector<capital_node>, minCapitalCompare> min_capital_queue;//小頂堆
	priority_queue<capital_node, vector<capital_node>, maxProfitCompare> max_profits_queue;//大頂堆
	for (int i = 0;i < Capital.size();i++)
	{
		capital_node node(Capital[i], Profits[i]);
		min_capital_queue.push(node);
	}
	for (int i = 0;i < k;i++)
	{
		while (!min_capital_queue.empty() && min_capital_queue.top().capital <= W)
		{
			capital_node temp = min_capital_queue.top();
			min_capital_queue.pop();
			max_profits_queue.push(temp);
		}
		while (max_profits_queue.empty())//大頂堆中已經沒有元素了
		{
			return W;
		}
		capital_node node = max_profits_queue.top();
		max_profits_queue.pop();
		W += node.profits;
	}
	return W;
}

第二種寫法:

思想都是一樣的,只是實現的方法不同。
下面是用c++ 的 multimap(按照鍵值來從小到大排序)實現的,則可以當作小頂堆來看待。而priority_queue內部是按照大根堆的來實現的。故可以不用寫比較策略

下面爲AC代碼:

int findMaximizedCapital(int k, int W, vector<int>& Profits, vector<int>& Capital) {
	multimap<int, int> m;//第一個參數表示 capital 第二個參數表示 profits
	for (int i = 0;i < Capital.size();i++)
	{
		m.insert(pair<int, int>(Capital[i], Profits[i]));//map 根據鍵值來從大到小排序
	}
	priority_queue<int> p_queue;//表示利潤的優先隊列,默認是大頂堆

	for (int i = 0;i < k;i++)
	{
		for (multimap<int, int>::iterator it = m.begin(); it != m.end(); it++)//遍歷小頂堆
		{
			if ((*it).first <= W)//表示當前花費沒有超過初始金額
			{
				p_queue.push((*it).second);
				m.erase(it);
			}
			else
			{
				break;
			}

		}

		if (p_queue.empty())//金額優先隊列爲空,即大頂堆爲空
		{
			break;
		}
		int profit = p_queue.top();
		p_queue.pop();
		W += profit;//現在的初始金額
	}
	return W;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章