买卖股票 | House Robber
Best Time to buy and sell stocks
买卖股票是一个系列问题,「状态」有三个,第一个是天数,第二个是允许交易的最大次数,第三个是当前的持有状态(即之前说的 rest 的状态,我们不妨用 1 表示持有,0 表示没有持有)。然后我们用一个三维数组就可以装下这几种状态的全部组合:
dp[i][k][0 or 1]
0 <= i <= n-1, 1 <= k <= K
n 为天数,大 K 为最多交易数
此问题共 n × K × 2 种状态,全部穷举就能搞定。
for 0 <= i < n:
for 1 <= k <= K:
for s in {0, 1}:
dp[i][k][s] = max(buy, sell, rest)dp[3][2][1]的含义就是:今天是第三天,我现在手上持有着股票,至今最多进行 2 次交易。dp[2][3][0]的含义:今天是第二天,我现在手上没有持有股票,至今最多进行 3 次交易。
我们想求的最终答案是 dp[n - 1][K][0],即最后一天,最多允许 K 次交易,最多获得多少利润。读者可能问为什么不是 dp[n - 1][K][1]?因为 [1] 代表手上还持有股票,[0] 表示手上的股票已经卖出去了,很显然后者得到的利润一定大于前者。
二、状态转移框架
现在,我们完成了「状态」的穷举,我们开始思考每种「状态」有哪些「选择」,应该如何更新「状态」。只看「持有状态」,可以画个状态转移图。

Best Time to Buy and Sell Stock IV
at most K transaction
最general的股票买卖题目
f[i][k][0 or 1] represents max profit after day i and making at most K transaction with state j, j can be 0 or 1, 1 means hold
Best Time to Buy and Sell Stock III
K=2的情况,套用IV模板就好
Best Time to Buy and Sell Stock I
At most one transaction, 即K = 1的情况
f[i][0] = max(f[i-1][0], f[i-1][1] + prices[i])
f[i][1] = max(f[i-1][1], - prices[i]) //注意,不是max(f[i-1][1], f[i-1][0] - prices[i])
Best Time to Buy and Sell Stock II
K= infinite的情况
这题可以用Greedy贪心来做
whenever prices[i] - prices[i - 1] >0, then add to profit
带冷却时间的情况
K = Infinite
带交易费的情况
K = Infinite
House Robber
相邻两家不能同时抢
House Robber II
收尾相连
所以针对收尾的两个房子有3种情况
both nums[0] and nums[n - 1] not rob
rob nums[0] only, not nums[n - 1]
rob nums[n - 1] only, not nums[0]
不用考虑第1种情况,因为结果可以被2,3 cover
可以转化为区间型 DP -> rob(int[] nums, int begin, int end)
House Robber III
抢劫的路径改为binary tree
这个反而更简单了,divide & conquer返回resultType
Tree DFS traverse不需要memo, 因为没有重复计算可以优化
Last updated
Was this helpful?