Best Time to Buy and Sell Stock IV

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

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

Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).

Example 1:

Input: [2,4,1], k = 2
Output: 2
Explanation: Buy on day 1 (price = 2) and sell on day 2 (price = 4), profit = 4-2 = 2.

Example 2:

Input: [3,2,6,5,0,3], k = 2
Output: 7
Explanation: Buy on day 2 (price = 2) and sell on day 3 (price = 6), profit = 6-2 = 4.
             Then buy on day 5 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.

思路:如果K >= n / 2,代表我能够买卖的次数已经超过了我能够买卖的极限,也就是当天买,第二天有利润就卖。那么我可以一直买卖,见利就收。题目变成了Best Time to Buy and Sell Stock II, 如果次数比较小,那么就要用dp;

这里我看了很多版本,觉得这个global和local的版本比较好理解;

global[i][j] 代表到第i天,最多交易j次,我全局能够得到的最大profit,全局的意思就是第i天,我可以啥也不做,也可以卖。

local[i][j] 代表的物理意义是:第i天,最多交易j次,而且第i天我必须卖的profit;

那么状态转移方程:全局的比较简单 global[i][j] = Math.max(global[i - 1][j], local[i][j]),这个没有问题。

局部的有点绕:local[i][j] = Math.max(part1, part2)

part1: (global[i - 1][j - 1] + Math.max(0, diff))也就是前一天全局最多和今天如果profit>0,我就卖,否则我不做任何事情。

part2: local[i - 1][j] + diff, 也就是我前一天卖了j次交易,但是最后一次交易我拖到第i天,次数不会增加,但是天数从[i - 1][j] 到了[i][j],注意的是无论diff >0 还是< 0,我都必须得卖的。这里是一个很tricky的地方,[i][j]的物理意义是第i天最多交易j次,但是j次的交易我可以拖时间,从i -1天拖到第i天,那么就是local[i - 1][j] 到local[i][j] 的状态转移方程;

class Solution {
    public int maxProfit(int k, int[] prices) {
        int n = prices.length;
        if(k >= n / 2) {
            return solveQuick(prices);
        }
        int[][] local = new int[n + 1][k + 1];
        int[][] global = new int[n + 1][k + 1];
        
        for(int i = 1; i < n; 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(0, diff), local[i - 1][j] + diff);
                global[i][j] = Math.max(global[i - 1][j], local[i][j]);
            }
        }
        return global[n - 1][k];
    }
    
    private int solveQuick(int[] prices) {
        int profit = 0;
        for(int i = 1; i < prices.length; i++) {
            if(prices[i] > prices[i - 1]) {
                profit += prices[i] - prices[i - 1];
            }
        }
        return profit;
    }
}

 

你可能感兴趣的:(Dynamic,Programming)