代码学习记录40---动态规划

随想录日记part40

t i m e : time: time: 2024.04.10



主要内容 :今天开始要学习动态规划的相关知识了,今天的内容主要涉及:

买卖股票的最佳时机加强版。



动态规划五部曲:

【1】.确定dp数组以及下标的含义

【2】.确定递推公式

【3】.dp数组如何初始化

【4】.确定遍历顺序

【5】.举例推导dp数组

Topic1买卖股票的最佳时机|||

思路:

接下来进行动规五步曲:

1.确定dp数组以及下标的含义:

一天一共就有五个状态,

  • 0.没有操作 (其实我们也可以不设置这个状态)
  • 1.第一次持有股票
  • 2.第一次不持有股票
  • 3.第二次持有股票
  • 4.第二次不持有股票

dp[i][j]中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]表示第i天状态j所剩最大现金。
需要注意:dp[i][1],表示的是第i天,买入股票的状态,并不是说一定要第i天买入股票,这是很多同学容易陷入的误区。例如 dp[i][1] ,并不是说 第i天一定买入股票,有可能 第 i-1天 就买入了,那么 dp[i][1] 延续买入股票的这个状态。

2.确定递推公式:

【达到dp[i][1]有两个操作】:

操作一:第i天买入股票了,那么dp[i][1] = dp[i-1][0] - prices[i]

操作二:第i天没有操作,而是沿用前一天买入的状态,即:dp[i][1] = dp[i - 1][1]

那么dp[i][1]究竟选 dp[i-1][0] - prices[i],还是dp[i - 1][1]呢?

一定是选最大的,所以 dp[i][1] = max(dp[i-1][0] - prices[i], dp[i - 1][1]);

【dp[i][2]也有两个操作】:

操作一:第i天卖出股票了,那么dp[i][2] = dp[i - 1][1] + prices[i]

操作二:第i天没有操作,沿用前一天卖出股票的状态,即:dp[i][2] = dp[i - 1][2]

所以dp[i][2] = max(dp[i - 1][1] + prices[i], dp[i - 1][2])

同理可推出剩下状态部分:

dp[i][3] = max(dp[i - 1][3], dp[i - 1][2] - prices[i]);

dp[i][4] = max(dp[i - 1][4], dp[i - 1][3] + prices[i]);

3.dp数组如何初始化

dp数组如何初始化

第0天没有操作,这个最容易想到,就是0,即:dp[0][0] = 0;

第0天做第一次买入的操作,dp[0][1] = -prices[0];

第0天做第一次卖出的操作,这个初始值应该是多少呢?

此时还没有买入,怎么就卖出呢? 其实大家可以理解当天买入,当天卖出,所以dp[0][2] = 0;

第0天第二次买入操作,初始值应该是多少呢?应该不少同学疑惑,第一次还没买入呢,怎么初始化第二次买入呢?

第二次买入依赖于第一次卖出的状态,其实相当于第0天第一次买入了,第一次卖出了,然后再买入一次(第二次买入),那么现在手头上没有现金,只要买入,现金就做相应的减少。

所以第二次买入操作,初始化为:dp[0][3] = -prices[0];

同理第二次卖出初始化dp[0][4] = 0;

4.确定遍历顺序

从递归公式其实已经可以看出,一定是从前向后遍历,因为dp[i],依靠dp[i - 1]的数值。

5.举例推导dp数组

以输入[1,2,3,4,5]为例
代码如下:

java 复制代码
class Solution {
  class Solution {
    public int maxProfit(int[] prices) {
        // 定义dp
        int len = prices.length;
        int[][] dp = new int[len][5];
        // 初始化
        dp[0][1] = -prices[0];
        dp[0][3] = -prices[0];
        // 状态转移
        for (int i = 1; i < len; i++) {
            dp[i][0] = dp[i - 1][0];
            dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
            dp[i][2] = Math.max(dp[i - 1][1] + prices[i], dp[i - 1][2]);
            dp[i][3] = Math.max(dp[i - 1][3], dp[i - 1][2] - prices[i]);
            dp[i][4] = Math.max(dp[i - 1][3] + prices[i], dp[i - 1][4]);
        }
        return dp[len - 1][4];

    }
}

时间复杂度 : O ( n ) O(n) O(n)
空间复杂度 : O ( n ∗ 5 ) O(n*5) O(n∗5)



Topic2买卖股票的最佳时机IV

题目:

思路:

参考上一题

java 复制代码
class Solution {
    public int maxProfit(int k, int[] prices) {
        // 定义dp
        int len = prices.length;
        int[][] dp = new int[len][2 * k + 1];
        // 初始化
        for (int i = 1; i < 2 * k + 1; i = i + 2) {
            dp[0][i] = -prices[0];
        }
        for (int i = 1; i < len; i++) {
            for (int j = 0; j < 2 * k - 1; j = j + 2) {
                dp[i][j + 1] = Math.max(dp[i - 1][j + 1], dp[i - 1][j] - prices[i]);
                dp[i][j + 2] = Math.max(dp[i - 1][j + 1] + prices[i], dp[i - 1][j + 2]);
            }
        }
        return dp[len - 1][2 * k];
    }
}

时间复杂度 : O ( n ∗ k ) O(n*k) O(n∗k)
空间复杂度 : O ( n ∗ k ) O(n*k) O(n∗k)



相关推荐
无限空间之王1 分钟前
我让三个 AI 互相竞争进化,两天后它们发明了一个我看不懂的算法
算法
洛阳泰山4 分钟前
开源智能体搭建平台MaxKB4j 技术文档
java·开源·llm·springboot·agent·rag·langchain4j
我命由我123459 分钟前
Android 开发 - UriMatcher(一个 URI 分类器)
android·java·java-ee·kotlin·android studio·android-studio·android runtime
sinat_255487819 分钟前
为 System.out 编写我们自己的包装类
java·开发语言·算法
a8a3029 分钟前
Springboot中CommandLineRunner的用法以及执行顺序的控制
java·spring boot·spring
Piccab0o16 分钟前
【学习笔记】——电磁相关
笔记·学习
阿Y加油吧20 分钟前
力扣打卡——盛最多水的容器、三数之和
算法·leetcode·排序算法
boy快快长大21 分钟前
【PyTorch】2.0 入门学习
人工智能·pytorch·学习
代码探秘者22 分钟前
【大模型应用】1.了解RAG
java·人工智能·python·spring
sevenlin25 分钟前
Spring Boot 经典九设计模式全览
java·spring boot·设计模式