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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章