参考
代码随想录
题目一:LeetCode 121. 买卖股票的最佳时机
注意这个题只买卖一次!!
贪心
class Solution {
public:
int maxProfit(vector<int>& prices) {
int low = INT_MAX;
int result = 0;
for(int i = 0; i < prices.size(); i++){
low = min(low,prices[i]);
result = max(result,prices[i] - low);
}
return result;
}
};
动态规划
- 确定dp数组下标及其含义
- dp[i][0]:第0至第i天(包括第i天)买入股票需要花费的最小金额
- dp[i][1]:第i天持有的最大利润
注意,两者的区别,dp[i][0]表示的是第0到第i天,是一个区间,在这个区间内买入需要花费的最少金额;而dp[i][1]表示的是第i天持有的利润,这里并不一定是第i天卖出,可能在之前就已经卖出了。
- 确定递推公式
- dp[i][0]
如果第i天才买入股票,那么需要花费prices[i]的费用;
如果第i-1天的时候已经买入了,那么花费的费用和第i-1天一样,即保持不变,dp[i][0] = dp[i-1][0]
因为最终要保证利润最大,因此要使得买入花费的费用最小,所以dp[i][0] = min(prices[i], dp[i-1][0])
- dp[i][1]
如果第i天卖出,那么第i天的利润为 prices[i] - dp[i][0]
如果第i天之前已经卖出,那么利润和前一天的一样,即保持不变,dp[i][1] = dp[i-1][1]
保证利润最大,因此dp[i][1] = max(prices[i] - dp[i][0], dp[i-1][1])
-
dp数组初始化
因为第i天的状态只涉及到第i-1天,因此只需要初始化i=0的时候即可,dp[0][0] = prices[0],dp[0][1] = 0 -
确定遍历顺序
从前往后遍历即可。 -
举例推导dp数组
完整的代码实现如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
vector<vector<int>> dp(prices.size(),vector<int>(2));
dp[0][0] = prices[0];
dp[0][1] = 0;
for(int i = 1; i < prices.size(); i++){
dp[i][0] = min(prices[i],dp[i-1][0]);
dp[i][1] = max(dp[i-1][1],prices[i]-dp[i][0]);
}
return dp.back()[1];
}
};
题目二:LeetCode 122. 买卖股票的最佳时机II
贪心
class Solution {
public:
int maxProfit(vector<int>& prices) {
int profit = 0;
for(int i = 1; i < prices.size(); i++)
profit += max(prices[i]-prices[i-1],0);
return profit;
}
};
动态规划
这个题和上一个题的区别在于可以多次买卖,主要体现在递推公式上。
- dp[i][0]:第0至第i天(包括第i天)买入股票需要花费的最小金额
- dp[i][1]:第i天持有的最大利润
因为上一个题只买卖一次,所以花费的金额只能是0-i天中的最小值,这里多次买卖,所以还需要考虑之前卖出所得的利润,这里的符号定义很好理解,花费的金额为正就是花钱,为负说明是收入。因此dp[i][0] = min(prices[i] - dp[i-1][1],dp[i-1][0])
,即当前花费的钱要减去上一次的卖出得到的利润,举个例子,在第i天买入一只股票,价格为3,之前买卖股票所得的利润为5,那么买入这只股票之后所花费的金额为3-5 = -2,为负说明即使买入股票之后还是盈利。
两个题的递推公式区别仅在于dp[i][0].
- 只买卖一次
dp[i][0] = min(prices[i],dp[i-1][0]); dp[i][1] = max(dp[i-1][1],prices[i]-dp[i][0]);
- 多次买卖
dp[i][0] = min(prices[i] - dp[i-1][1],dp[i-1][0]); dp[i][1] = max(dp[i-1][1],prices[i]-dp[i][0]);
一次买卖和多次买卖的dp数组推导区别:
本题完整的代码实现如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
vector<vector<int>> dp(prices.size(),vector<int>(2));
dp[0][0] = prices[0];
dp[0][1] = 0;
for(int i = 1; i < prices.size(); i++){
dp[i][0] = min(prices[i] - dp[i-1][1],dp[i-1][0]);
dp[i][1] = max(dp[i-1][1],prices[i]-dp[i][0]);
}
return dp.back()[1];
}
};