1. 买卖股票的最佳时机
- 普通遍历方法: 每次记录最小值,然后用当前值dp[i]相减 与当前最大利润值max_val对比
// 贪心
int maxProfit1(vector<int>& prices) {
vector<int> dp(prices.size(), 0);
int min_price = prices[0];
int max_val = 0;
for(int i=1; i<prices.size(); i++){
min_price = min(min_price, prices[i]);
max_val = max(max_val, prices[i]-min_price);
}
return max_val;
}
- 动态规划, 二维数组存储 当天持有股票和不持有股票所能获得的最大利润
int maxProfit(vector<int>& prices) {
/*
1.二维dp数组, dp[i][0]代表当天持有股票所能获得的最大利润
dp[i][1]代表当天不持有股票所能获得的最大利润
这里持有的意思不一定是当天买,也有肯能是昨天买入的
2.确定递推公式
第i天持有股票所能获得的最大利润dp[i][0],由两个状态推出
(1):第i-1天持有股票,就保持现状,所持有的现金就是昨天持有股票得到的现金dp[i][0] = dp[i-1][0]
(2):第i-1天不持有股票,所得现金就是 -prices[i]
dp[i][0] = max(dp[i-1][0], -prices[i])
第i天不持有股票获得的最大利润dp[i][1] 也由2个状态推出
(1): 第 i-1 没有股票就继续保持, dp[i][1] = dp[i-1][1]
(2): 第i-1天有股票,把手里持有的股票卖出, dp[i][1] = prices[i] + dp[i-1][0]
dp[i][1] = max(dp[i-1][1], prices[i]+dp[i-1][0])
3.初始化
由递推公式可以看出,基础都是从 dp[0][0] 和 dp[0][1]推出
dp[0][0] 第0天持有股票, dp[0][1]第0天不持有股票
dp[0][0] = -prices[0], dp[0][1] = 0
*/
int len = prices.size();
if(len == 0) return 0;
vector<vector<int>> dp(len, vector<int>(2, 0));
dp[0][0] = -prices[0];
dp[0][1] = 0;
for(int i=1; i<prices.size(); i++){
// 1.持有股票 dp[i][0], 当天购买或者前面就已经买到
dp[i][0] = max(dp[i-1][0], -prices[i]);
// 2.不持有股票, 当天卖出或者本来就不持有
dp[i][1] = max(dp[i-1][1], prices[i]+dp[i-1][0]);
}
return dp[len-1][1];
}
2. 买卖股票的最佳时机 II (不限制购买和卖出次数)
class Solution {
public:
// 动态规划
int maxProfit(vector<int>& prices){
// dp[i][0] 第i天持有的最多现金
// dp[i][1] 第i天不持有股票的最多现金
int len = prices.size();
vector<vector<int>> dp(2, vector<int>(2));
// dp[0][0]第0天持有股票, dp[0][1]第0天不持有股票
dp[0][0] = -prices[0];
dp[0][1] = 0;
for(int i=1; i<len; i++){
// 持有的话两种情况: 前几天就买入 或者 当天买入
dp[i % 2][0] = max(dp[(i-1) % 2][0], dp[(i-1) % 2][1] - prices[i]);
// 不持有: 前几天就没买 或者 当天卖出
dp[i % 2][1] = max(dp[(i-1) % 2][1], dp[(i-1) % 2][0] + prices[i]);
}
return dp[(len-1) % 2][1];
}
// 贪心算法
int maxProfit1(vector<int>& prices) {
int result = 0;
for(int i=0; i<prices.size()-1; i++){
result += max(prices[i+1] - prices[i], 0);
}
return result;
}
};