- IPO
给定若干个项目。对于每个项目 i,它都有一个纯利润 Pi,并且需要最小的资本 Ci 来启动相应的项目。最初,你有 W 资本。当你完成一个项目时,你将获得纯利润,且利润将被添加到你的总资本中。总而言之,从给定项目中选择最多 k 个不同项目的列表,以最大化最终资本,并输出最终可获得的最多资本。
只考虑利润,那么这就是完美的贪心算法了。用小顶堆存资本,大顶堆存利润,循环K次,寻找满足资本的放入利润堆,然后从资本堆pop出去。
class Solution {
public:
int findMaximizedCapital(int k, int W, vector<int>& Profits, vector<int>& Capital) {
priority_queue<int> p; // 利润 大根堆
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> c; // 资本 小根堆
for (int i = 0; i < Capital.size(); i++) {
c.emplace(make_pair(Capital[i], Profits[i]));
}
for (int i = 0; i < k; i++) {
while (!c.empty() && c.top().first <= W) {
// 资本小于等于W的项目,存入利润大根堆
p.emplace(c.top().second);
c.pop();
}
if(p.empty()) break;
W += p.top(); // 每次选利润最大的
p.pop();
}
return W;
}
};
- 下一个更大元素2
给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。
单调栈的典型应用,逆序比较方便
class Solution
{
public:
vector<int> nextGreaterElements(vector<int>& nums)
{
int n = nums.size();
vector<int> ret(n, -1);
stack<int> m_stack;
if (n == 0) return ret;
for (int i = 2 * n - 1; i >= 0; i--)`在这里插入代码片`
{
while (m_stack.size() && m_stack.top() <= nums[i % n])
{
m_stack.pop();
}
if (m_stack.size())
{
ret[i % n] = m_stack.top();
}
m_stack.push(nums[i % n]);
}
return ret;
}
};
- 七进制数
给定一个整数,将其转化为7进制,并以字符串形式输出。
简单的进制运算
class Solution {
public:
string convertToBase7(int num)
{
bool low = false;
string ret;
if (num < 0)
{
low = true;
num = -num;
}
while (num >= 7)
{
ret = (char)(num % 7 + '0') + ret;
num = num / 7;
}
ret = (char)(num + '0') + ret;
if (low) ret = '-' +ret;
return ret;
}
};
- 相对名次
给出 N 名运动员的成绩,找出他们的相对名次并授予前三名对应的奖牌。前三名运动员将会被分别授予 “金牌”,“银牌” 和“ 铜牌”(“Gold Medal”, “Silver Medal”, “Bronze Medal”)。
用一个红黑树map保存,k为分数,v为索引,红黑树会自带排序,因此直接遍历即可输出名次
class Solution {
public:
string tostr(int n){
if(n==1) return "Gold Medal";
if(n==2) return "Silver Medal";
if(n==3) return "Bronze Medal";
return to_string(n);
}
vector<string> findRelativeRanks(vector<int>& nums) {
int n = nums.size();
vector<string> result(n);
map<int, int> m;
for (int i=0; i<n; i++) m[nums[i]] = i;
for (const auto &it:m) {
result[it.second] = tostr(n--);
}
return result;
}
};
- 完美数
对于一个 正整数,如果它和除了它自身以外的所有 正因子 之和相等,我们称它为 「完美数」。给定一个 整数 n, 如果是完美数,返回 true,否则返回 false
只要找到平方根即可,然后将除数和余数都加起来
class Solution {
public:
bool checkPerfectNumber(int num)
{
if (num == 1) return false;
int ret = 1;
for (int i = 2; i <= num / i; i++)
{
if (num % i == 0)
{
ret += i;
if (i * i != num)
{
ret += num / i;
}
}
}
return ret == num;
}
};
- 出现次数最多的子树元素和
给你一个二叉树的根结点,请你找出出现次数最多的子树元素和。一个结点的「子树元素和」定义为以该结点为根的二叉树上所有结点的元素之和(包括结点本身)。你需要返回出现次数最多的子树元素和。如果有多个元素出现的次数相同,返回所有出现次数最多的子树元素和(不限顺序)。
很简单的一道题:首先DFS获取每个字数元素和,然后遍历一遍取最大值即可
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
unordered_map<int,int> hash;
int dfs(TreeNode* r){
//返回以r为根的子树和
if(!r) return 0;
int ans = r->val + dfs(r->left) + dfs(r->right);
hash[ans]++;
return ans;
}
vector<int> findFrequentTreeSum(TreeNode* root) {
dfs(root);
vector<int> ans;
int maxx = 0;//出现次数的最大值
for(auto [x, y] : hash){
//寻找最大值
if(y < maxx) continue;//小的直接忽略
if(y > maxx) ans.clear(),maxx = y;//出现更大的 则清空 替换
ans.push_back(x);
}
return ans;
}
};