力扣第188题 买卖股票的最佳时机 IV c++ 动态规划题 附Java代码

题目

188. 买卖股票的最佳时机 IV

困难

相关标签

 数组   动态规划

给你一个整数数组 prices 和一个整数 k ,其中 prices[i] 是某支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。也就是说,你最多可以买 k 次,卖 k 次。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

示例 1:

输入:k = 2, prices = [2,4,1]
输出:2
解释:在第 1 天 (股票价格 = 2) 的时候买入,在第 2 天 (股票价格 = 4) 的时候卖出,这笔交易所能获得利润 = 4-2 = 2 。

示例 2:

输入:k = 2, prices = [3,2,6,5,0,3]
输出:7
解释:在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。
     随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。

提示:

  • 1 <= k <= 100
  • 1 <= prices.length <= 1000
  • 0 <= prices[i] <= 1000

思路和解题方法

  1. 首先创建了一个二维数组 dp,用来存储每个状态下的最大收益。数组的行数为 prices 数组的大小,列数为 2*k+1,因为每次交易包括买入和卖出两个操作。
  2. 接着,通过两层循环遍历 prices 数组和 dp 数组,计算每个状态下的最大收益。其中,第一层循环是遍历 prices 数组,第二层循环是遍历每次交易的买入和卖出操作。
  3. 在每次交易的买入操作中,使用状态转移方程 dp[i][j+1] = max(dp[i-1][j+1], dp[i-1][j] - prices[i]),表示当前状态下选择买入或保持不变的最大收益。
  4. 在每次交易的卖出操作中,使用状态转移方程 dp[i][j+2] = max(dp[i-1][j+2], dp[i-1][j+1] + prices[i]),表示当前状态下选择卖出或保持不变的最大收益。
  5. 最后,返回 dp[prices.size() - 1][2*k],即最后一天,进行了2k次交易后的最大收益。

复杂度

        时间复杂度:

                O(n*k)

        时间复杂度为O(n*k),其中n是prices数组的大小,k是最多可以进行的交易次数。

在第一个循环中,遍历了2k个元素,而在第二个循环中,遍历了n个元素,所以总的时间复杂度为O(nk)。

        空间复杂度

                O(n*k)

        空间复杂度方面,使用了一个二维数组dp来存储每个状态下的最大收益,其大小为prices.size() * (2k+1)。因此,空间复杂度也是O(nk),随着输入规模的增加,空间消耗会相应增加。

c++ 代码

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        // 创建一个二维数组 dp,用来记录每天的最大收益
        vector<vector<int>> dp(prices.size(), vector<int>(2 * k + 1, 0));

        // 初始化第一天的买入状态
        for (int j = 1; j <= 2 * k; j += 2) {
            dp[0][j] = -prices[0];
        }

        // 遍历每一天的状态
        for (int i = 1; i < prices.size(); i++) {
            // 遍历偶数列,即卖出状态
            for (int j = 0; j < 2 * k - 1; j += 2) {
                // 更新买入状态和卖出状态的最大收益
                dp[i][j + 1] = max(dp[i - 1][j + 1], dp[i - 1][j] - prices[i]);
                dp[i][j + 2] = max(dp[i - 1][j + 2], dp[i - 1][j + 1] + prices[i]);
            }
        }

        return dp[prices.size() - 1][2 * k];
    }
};

附Java代码

class Solution {
    public int maxProfit(int k, int[] prices) {
        if (prices.length == 0) return 0;

        // [天数][股票状态]
        // 股票状态: 奇数表示第 k 次交易持有/买入, 偶数表示第 k 次交易不持有/卖出, 0 表示没有操作
        int len = prices.length;
        int[][] dp = new int[len][k*2 + 1];
        
        // dp数组的初始化, 与版本一同理
        for (int i = 1; i < k*2; i += 2) {
            dp[0][i] = -prices[0];
        }

        for (int i = 1; i < len; i++) {
            for (int j = 0; j < k*2 - 1; 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 + 2], dp[i - 1][j + 1] + prices[i]);
            }
        }
        return dp[len - 1][k*2];
    }
}

觉得有用的话可以点点赞,支持一下。

如果愿意的话关注一下。会对你有更多的帮助。

每天都会不定时更新哦  >人<  。

posted @   lenyan~  阅读(16)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示