携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第25天,卖股票的最佳时机II[贪心 || 动态规划] - 掘金 (juejin.cn)
前言
卖股票的最佳时机,我们可以看其全貌进行股票交易,不会说错过了昨天今天就不能操作了,可采用贪心进行假买假卖。这也是经典的动态规划练习题,持有/不持有股票两种状态,每天的两种状态都是前一天的两种状态转移过来,取最大即可。
一、卖股票的最佳时机
二、贪心 & 状压动规
1、贪心
// 先分析思考,并记录思路,再coding,拒绝秒杀,希望有一个思考分析记录的锻炼过程。
/*
只要碰到股票比前一天下跌了就卖出去(贪心点),当前后形成逆序,其实是一个假买假卖的动作,即今天判断,却以昨天的状态卖了。
假买假卖,其实当天没有买,因为收益没有减去buyPrices,其实当前没有卖,而是想着该前一天把他卖了。站在未来的视角,却做着昨天的事。
*/
public int maxProfit(int[] prices) {
int buyPrice = prices[0];
int sumProfit = 0;
for(int i = 1;i < prices.length;i++){
// 如果股票开始跌了,马上卖。
if(prices[i] < prices[i - 1]) {
sumProfit += prices[i - 1] - buyPrice;
// 新一次手持股票价格
buyPrice = prices[i];
}
}
// 正常结束循环,需要把股票卖了,才会增加一笔收益。
return sumProfit + prices[prices.length - 1] - buyPrice;
}
2、状压动规
状态定义:f[i]第i天的收益;
第i天有什么状态?持有股票和不持有股票 -> f[i][2];
第i天持有/不持有股票的收益如何得到?前一天持有/前一天不持有 + 买卖股票得来;
最终状态:f[n - 1][0]:最后一天不持有股票时的收益。
// 每天可持有股票和不持有股票两种状态,而当天是否持有股票和前一天持有/不持有股票的收益有关。
public int maxProfit(int[] prices) {
int[] f = new int[2];// 持有和不持有股票,由于前后相关,所以状态降维。
f[1] = -prices[0];
for(int i = 1;i < prices.length;i++){
int old = f[0];
f[0] = Math.max(old,f[1] + prices[i]);// 看卖了是否不如当初就不买。
f[1] = Math.max(f[1],old - prices[i]);// 看是持有那天的股票才是收益最高的。
}
return f[0];
}
总结
1)贪心问题,分析贪心点所在,进行问题转换,再选择合适的数据结构与经典的算法思想,完成题解。
2)动态规划,本质将大问题分解成规模更小但性质相同的递推问题,分析并抓住各种状态 & 状态定义(记录什么时候的效果,如第i天持有股票的收益) & 状态的转移关系 & 最终状态。
3)先分析思考,并记录思路,再coding,拒绝秒杀,希望有一个思考分析记录的锻炼过程。