【Java力扣算法】LeetCode 309 Best Time to Buy and Sell Stock with Cooldown(动态规划)

题目:

给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。​

设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):

  • 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
  • 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。

示例:

输入: [1,2,3,0,2]
输出: 3 
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]

 

思路:

      动态规划就是通过状态转移公式,也就是   当前状态和 下一状态的对比,比出哪个更好就取用哪个。

      对于这个题来说就是  sell的时候,其实就是比较  昨天卖比较好还是今天卖比较好,所以就是sell[i] = max(sell[i] , sell[i-1]),因为sell[i] =sell[i]就没意义了,所以这时候就要找一个sell[i]的替代品,所以推理一下第i天卖sell[i]就=当前价格price[i] - 从前一天算起的最合理买入价格buy[i-1]。由此可以推出一个状态转移方程     sell(i) = max(sell(i - 1) ,price(i) - buy(i - 1))。

      同理  买入的时候就是比较今天买比较好还是昨天买比较好。buy[i] = max(buy[i] , buy[i - 1])--->max(buy[i - 1] , sell(i - 2) - price(i))。其中替换buy(i) 的sell(i - 2) - price(i) 的意思就是上一次卖出后 又买入挣得钱。为什么是sell(i -2)原因就是有一天的冻结期,如果没有冻结期的话就是sell(i - 1)了。

      这时候再把 冻结期加上,因为冻结期就是因为前一天卖了,所以第二天才会冻结,所以cooldown(i) = sell(i - 1)。

      所以先定义dp二维数组,因为有三个变量,所以用第二维用来区分(dp[i][0] 表示卖的时候可以挣的最多的钱,dp[i][1]表示买的时候可以挣的最多的钱,dp[i][2]表示冻结时期时候  能挣的最多的钱)

通过一个例子来逐步解释解释:

价格  1  2  3  0  1  0  6
冻结  0  0  1  2  2  2  2
卖出  0  1  2  2  2  2  8  比较前一天卖整的多还是当天买挣的多sell(i-1),sell(i)--> sell(i-1) buy(i-1)+price(i)
买入 -1 -1 -1  1  1  2  2  比较前一天买挣得多还是当天买挣得多buy(i-1),buy(i)  --> buy(i-1) sell(i-2)-price(i) 

 

 

代码:

    public static int maxProfit(int[] prices) {
        int[][] dp=new int[prices.length][3];
        //添加边界判断条件
        if(prices == null || prices.length < 2)  return 0;
        //定义三个数组,买的 卖的 冻结的时刻可以挣的最多的钱。
        dp[0][0]=0;//sell
        dp[0][1]= - prices[0];//buy
        dp[0][2]=0;//cooldown
        for(int i = 1 ;i < prices.length ;i++){
            dp[i][0]=Math.max(dp[i - 1][0],dp[i - 1][1] + prices[i]);
            dp[i][1]=Math.max(dp[i - 1][1],dp[i - 1][2] - prices[i]);
            dp[i][2]=dp[i - 1][0];
        }
        return Math.max(dp[prices.length - 1][0],dp[prices.length - 1][2]);
    }

 

结果:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值