122. 买卖股票的最佳时机 II - 力扣(LeetCode)
因为上一题dp,这一题一直想怎么dp,然后就卡壳了。。。
其实就一张图的事(来自官方题解:买卖股票的最佳时机 II - 买卖股票的最佳时机 II - 力扣(LeetCode)):
Total Profit = ∑ i ( height ( peak i ) − height ( valley i ) ) \text {Total Profit}=\sum_{i}\left(\text {height}\left(\text {peak}_{i}\right)-\text {height}\left(\text {valley}_{i}\right)\right) Total Profit=i∑(height(peaki)−height(valleyi))
其实这有点像贪心的思路
class Solution {
public:
int maxProfit(vector& prices) {
int n = prices.size();
int vally = prices[0], peak = prices[0], res = 0;
int i = 0;
while(i < n-1){//
while(i < n-1 && prices[i] >= prices[i+1]) ++i;
vally = prices[i];
while(i < n-1 && prices[i] <= prices[i+1]) ++i;
peak = prices[i];//如果一直没有找到峰或者谷,那最后vally,peak均等于最后一个元素
res += peak - vally;
}
return res;
}
};
其实转化一下,当某个元素比它的前一个元素要大的时候,就可以累加差值,都不用考虑波峰后者波谷:
class Solution {
public:
int maxProfit(vector& prices) {
int n = prices.size();
int res = 0;
for(int i = 1; i < n; ++i){
if(prices[i] > prices[i-1]) res += prices[i] - prices[i-1];
}
return res;
}
};
至于这样为什么能行,可以看一下:暴力搜索、贪心算法、动态规划 - 买卖股票的最佳时机 II - 力扣(LeetCode)的方法二的解释。
这个题动态规划还是可以用的,之前想不出状态怎么转移,看了下面的题解之后还是明白了。
注意题目给的数组是一只股票在不同日期的价格。
每一天可能有三种动作:买,卖,什么都不做
二维dp:第一维表示日期(第几天),第二维表示(这一天结束之前)是否持有股票(1:有,0:无),数组值表示收益:
vector> dp(n, vector(2, 0));
第一种情况,当天(结束之前)手上没有股票,走到这一步有两种可能:
第二种情况,当天(结束之前)手上有股票,走到这一步也有两种可能:
我们要使得收益最大,所以状态转移的时候在两种情况中取收益较大者,有:
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i])
dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])
第i天的状态只能由第i-1天的状态推导而来,那么i = 0(第一天)的状态定义为:
dp[0][0] = 0; //第一天没有股票,没有任何动作,收益为0
dp[0][1] = 0 - prices[0]; //第一天(结束之前)有股票,说明今天进行了买入,收益为负(花掉一笔钱)
class Solution {
public:
int maxProfit(vector& prices) {
int n = prices.size();
if(n < 2) return 0;
//第一维表示日期,第二维表示是否持有股票(1:有,0:无),数组值表示收益
vector> dp(n, vector(2, 0));
dp[0][0] = 0; //第一天没有股票,没买没卖,收益为0
dp[0][1] = 0 - prices[0]; //第一天有股票,说明买入了,收益为负(花掉一笔钱)
for(int i = 1; i < n; ++i){
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i]);//第i天没有股票
dp[i][1] = max(dp[i-1][0] - prices[i], dp[i-1][1]);//第i天持有股票
}
//return max(dp[n-1][0], dp[n-1][1]);要想收益最大,最后一天肯定不会进行买入,所以dp[n-1][0]肯定更大
return dp[n-1][0];
}
};
这道题的dp其实不难写,但是很难解释,这位同学解释的很好:股票交易系列:贪心思想和动态规划 - 买卖股票的最佳时机 II - 力扣(LeetCode)