**[Lintcode]Best Time to Buy and Sell Stock IV 买卖股票的最佳时机 IV Leetcode

本文介绍了一种算法,用于计算给定股票价格数组时,在最多进行k次交易的情况下所能获得的最大利润。通过动态规划的方法,利用两个一维滚动数组分别记录以某天为最后一次卖出时的最大收益和整体最大收益。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Say you have an array for which the ith element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete at most ktransactions.

Example

Given prices = [4,4,6,1,1,4,2,5], and k = 2, return 6.

分析:使用二维数组,res[i][j]代表0~i中,交易j次的最大收益。

状态转移方程为:

local[i][j] = max(global[i-1][j-1] + max(diff,0), local[i-1][j]+diff)
global[i][j] = max(local[i][j], global[i-1][j])
因为在计算local[i][j]时,i-1,交易了j次,并且位置i因为和第j次交易相邻,可以并入第j次交易的情况,所以需要使用两个数组,一个数组local记录以i为最后一次卖出时,最大收益,和一个数组global,记录0到i范围内整体最大收益。这样local可以用来计算之前提到的交易合并问题。

以下方法运行内存超出规定大小。

class Solution {
    /**
     * @param k: An integer
     * @param prices: Given an integer array
     * @return: Maximum profit
     */
    public int maxProfit(int k, int[] prices) {
        if(prices == null || prices.length == 0) return 0;
        int[][] local = new int[prices.length][k + 1];
        int[][] global = new int[prices.length][k + 1];

        int res = 0;
        for(int j = 1; j <= k; j++) {
            for(int i = 1; i < prices.length; i++) {
                int diff = prices[i] - prices[i - 1];
            
                local[i][j] = Math.max(local[i - 1][j] + diff, 
                    global[i - 1][j - 1] + Math.max(0, diff));
                    
                global[i][j] = Math.max(global[i - 1][j], local[i][j]);
            }
        }
        return global[prices.length - 1][k];
    }
};

考虑使用两个滚动数组代替。滚动数组要确保覆盖后的值不会被用到。因此又引入了临时变量tmp。

现在内存符合要求,但是超时。继续改。

class Solution {
    /**
     * @param k: An integer
     * @param prices: Given an integer array
     * @return: Maximum profit
     */
    public int maxProfit(int k, int[] prices) {
        if(prices == null || prices.length == 0) return 0;
        int[] global = new int[prices.length];
        int[] local = new int[prices.length];
        
        int res = 0;
        for(int j = 1; j <= k; j++) {

            int tmp = global[0];
            for(int i = 1; i < prices.length; i++) {
                int diff = prices[i] - prices[i - 1];
                local[i] = Math.max(local[i - 1] + diff, 
                    tmp + Math.max(0, diff));
                
                tmp = global[i];
                global[i] = Math.max(global[i - 1], local[i]);
                if(global[i] > res) res = global[i];
            }
        }
        return res;
    }
};

当i小于j时,例如3个交易日需要进行4次交易的情况,可以以排除,所以给i加上限制。i>=j.  通过测试。

class Solution {
    /**
     * @param k: An integer
     * @param prices: Given an integer array
     * @return: Maximum profit
     */
    public int maxProfit(int k, int[] prices) {
        if(prices == null || prices.length == 0) return 0;
        int[] global = new int[prices.length];
        int[] local = new int[prices.length];
        //Memory Limit Exceeded,改用两个一维滚动数组
		
        int res = 0;
        for(int j = 1; j <= k; j++) {

            int tmp = global[0];
            for(int i = j; i < prices.length; i++) {
                int diff = prices[i] - prices[i - 1];
                local[i] = Math.max(local[i - 1] + diff, 
                    tmp + Math.max(0, diff));
                
                tmp = global[i];
                global[i] = Math.max(global[i - 1], local[i]);
                if(global[i] > res) res = global[i];
            }
        }
        return res;
    }
};





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值