LeetCode题号300+
309. 最佳买卖股票时机含冷冻期
给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
思路
- dp,由于每次只用数组的前一个值,所以可以优化一下空间复杂度
class Solution {
public:
int maxProfit(vector<int>& prices) {
if (!prices.size()) {
return 0;
}
int dp[prices.size()][3];// 0手中有股票,1封闭期,2没封闭
dp[0][0] = -prices[0];
dp[0][1] = dp[0][2] = 0;
for (int i = 1;i < prices.size();i++) {
dp[i][0] = max(dp[i-1][0],dp[i-1][2] - prices[i]);
dp[i][1] = dp[i-1][0] + prices[i];
dp[i][2] = max(dp[i-1][1],dp[i-1][2]);
}
return max(dp[prices.size()-1][2],dp[prices.size()-1][1]);
}
};
322. 零钱兑换
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
你可以认为每种硬币的数量是无限的。
思路
- dp
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
int dp[amount+10];
memset(dp,0x3f,sizeof(dp));
dp[0] = 0;
for (int i = 1;i <= amount;i++) {
for (int j = 0;j < coins.size();j++) {
if (i >= coins[j]) dp[i] = min(dp[i],dp[i-coins[j]]+1);
}
}
return dp[amount] == 0x3f3f3f3f ? -1 : dp[amount];
}
};
337. 打家劫舍 III
在上次打劫完一条街道之后和一圈房屋后,小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为“根”。 除了“根”之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果两个直接相连的房子在同一天晚上被打劫,房屋将自动报警。
计算在不触动警报的情况下,小偷一晚能够盗取的最高金额。
思路
- 选择当前点时,不选择左右节点
- 不选择当前点时,取左右子树的最大值
class Solution {
public:
unordered_map<TreeNode*,int> f,g;// f 选择当前节点,g 不选择
void back(TreeNode* root) {
if (root == NULL) {
return ;
}
back(root->left);
back(root->right);
f[root] = root->val + g[root->left] + g[root->right];
g[root] = max(f[root->left],g[root->left]) + max(f[root->right],g[root->right]);
}
int rob(TreeNode* root) {
back(root);
return max(f[root],g[root]);
}
};
338. 比特位计数
给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。
思路
- 对于任意一个正整数,其结果是将二进制位最后一个1置为0的结果+1
class Solution {
public:
vector<int> countBits(int num) {
vector<int> dp;
dp.push_back(0);
for (int i = 1;i <= num;i++) {
dp.push_back(dp[i&(i-1)]+1);
}
return dp;
}
};
347. 前 K 个高频元素
给定一个非空的整数数组,返回其中出现频率前 *k* 高的元素。
思路
- 计算出每个元素的出现次数,然后问题就变成了返回出现次数前k高的元素了
- 这时候可以用堆的形式
class Solution {
public:
static bool cmp(pair<int,int> x,pair<int,int> y) {
return x.second > y.second;
}
vector<int> topKFrequent(vector<int>& nums, int k) {
unordered_map<int,int> mp;
priority_queue<pair<int,int>,vector<pair<int,int>>,decltype(&cmp)> q(cmp);
vector<int> ans;
for (int i = 0;i < nums.size();i++) {
mp[nums[i]]++;
}
for (auto value : mp) {
if (q.size() < k) {
q.push(value);
} else if (q.top().second < value.second) {
q.pop();
q.push(value);
}
}
while (!q.empty()) {
ans.push_back(q.top().first);
q.pop();
}
return ans;
}
};
739. 每日温度
请根据每日
气温
列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用0
来代替。例如,给定一个列表
temperatures = [73, 74, 75, 71, 69, 72, 76, 73]
,你的输出应该是[1, 1, 4, 2, 1, 1, 0, 0]
。提示:
气温
列表长度的范围是[1, 30000]
。每个气温的值的均为华氏度,都是在[30, 100]
范围内的整数。
思路
-
温度范围[30,100],先遍历温度列表,再遍历[x,100]
-
class Solution { public: vector<int> dailyTemperatures(vector<int>& T) { vector<int> ans; queue<int> q[101]; for (int i = 0;i < T.size();i++) { q[T[i]].push(i); } for (int i = 0;i < T.size();i++) { int index = T.size(); for (int j = T[i]+1;j <= 100;j++) { if (!q[j].empty()) { index = min(q[j].front(),index); } } q[T[i]].pop(); ans.push_back(index == T.size() ? 0 : index-i ); } return ans; } };
-
单调栈,让栈单调递减
-
class Solution { public: vector<int> dailyTemperatures(vector<int>& T) { vector<int> ans(T.size()); stack<int> s; for (int i = 0;i <= T.size();i++) { while (!s.empty() && (i == T.size() || T[s.top()] < T[i])) { ans[s.top()] = (i == T.size() ? 0 : i - s.top()); s.pop(); } s.push(i); } return ans; } };