LeetCode Best Time to Buy and Sell Stock III

23 篇文章 0 订阅
20 篇文章 0 订阅

原题链接在这里:https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/

本题是Best Time to Buy and Sell Stock的进阶版。思路也很相似,仍旧是维护一个全局最优,一个局部最优。

这里最多可以进行k次交易,就是Best Time to Buy and Sell Stock IV让后本题把k变成2即可。

全局最优global是到达第i天可以最多进行j次交易的利润是多少,局部最优local是必须在第i天进行最后一次交易的利润。先更新局部最优:

local[i][j] = max(global[i-1][j-1] + max(diff,0), local[i-1][j] + diff)

diff是今天与昨天的差价, global[i-1][j-1] + max(diff,0)是指到第i-1天最多进行j-1次交易时的利润,加上进天得最后一次交易。

后一项是local[i-1][j] + diff是指在i-1天就进行了最多j次交易,i天进行最后一次交易,原本是i-1天卖的现在变成i天卖。

然后是更新全局变量:

global[i][j] = max(global[i-1][j], local[i][j])

比较前一天的全局最优和当天的局部最优,取大的那一个。

Note: Method 2 用了降维方法节省空间。但是注意双重loop 的内层loop, j是从k向小变到1,因为一维空间只能保存当前一行内容,更新local时用到了了local[i-1][j-1],若是从前往后走到了i,j时,[i-1][j-1]会被[i][j-1]覆盖掉,所以要从后往前走。

AC Java:

public class Solution {
    public int maxProfit(int[] prices) {
        return helper(prices,2);
    }
    private int helper(int[] prices, int k){
        if(prices == null || prices.length == 0){
            return 0;
        }
        /*
        //Method 1
        int[][] local = new int[prices.length][k+1];
        int[][] global = new int[prices.length][k+1];
        for(int i = 1; i<prices.length; i++){
            int diff = prices[i]-prices[i-1];
            for(int j = 1; j<=k; j++){
                local[i][j] = Math.max(global[i-1][j-1] + Math.max(diff,0), local[i-1][j]+diff);
                global[i][j] = Math.max(global[i-1][j], local[i][j]);
            }
        }
        return global[prices.length-1][k];
        */
        
        //Method 2
        int [] local = new int[k+1];
        int [] global = new int[k+1];
        for(int i = 1; i<prices.length; i++){
            int diff = prices[i]-prices[i-1];
            for(int j = k; j>=1; j--){
                local[j] = Math.max(global[j-1] + Math.max(diff,0), local[j]+diff);
                global[j] = Math.max(global[j], local[j]);
            }
        }
        return global[k];
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值