动手刷LeetCode--股票问题

解题思路

穷举框架
不用递归思想进行穷举,而是利用「状态」进行穷举;看看总共有几种可能的「状态」,再找出每个「状态」对应的「选择」;穷举所有「状态」,穷举的目的是根据对应的「选择」更新状态。

具体实现框架格式:

for 状态1 in 状态1的所有取值:
for 状态2 in 状态2的所有取值:
for …
dp[状态1][状态2][…] = 择优(选择1,选择2…)

对应股票问题,状态进行描述

每天都有三种「选择」:买入、卖出、无操作,我们用 buy, sell, rest 表示这三种选择。但问题是,并不是每天都可以任意选择这三种选择的,因为 sell 必须在 buy 之后,buy 必须在 sell 之后。那么 rest 操作还应该分两种状态,一种是 buy 之后的 rest(持有了股票),一种是 sell 之后的 rest(没有持有股票)。而且别忘了,我们还有交易次数 k 的限制,就是说你 buy 还只能在 k > 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)

状态图来描述问题,思考问题;

知识点

动态规划:关键就是数组定义和状态转移方程;

代码实现:

public int maxProfit(int[] prices) {
    if (prices.length == 0) {
        return 0;
    }
    int K = 2;
    int[][] dp = new int[prices.length][K + 1];
    for (int k = 1; k <= K; k++) {
        int min = prices[0];
        for (int i = 1; i < prices.length; i++) {
            //找出第 1 天到第 i 天 prices[buy] - dp[buy][k - 1] 的最小值 
            min = Math.min(prices[i] - dp[i][k - 1], min); 
            //比较不操作和选择一天买入的哪个值更大
            dp[i][k] = Math.max(dp[i - 1][k], prices[i] - min);
        }
    }
    return dp[prices.length - 1][K];
}

加油坚持,所有大神都是从小白菜鸟一步一步受虐走过来的
自己不放弃

发布了39 篇原创文章 · 获赞 3 · 访问量 2521

猜你喜欢

转载自blog.csdn.net/li_kin/article/details/104704693