LeetCode – Best Time to Buy and Sell Stock IV (Java)

Problem

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 k transactions.

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

Analysis

This is a generalized version of Best Time to Buy and Sell Stock III. If we can solve this problem, we can also use k=2 to solve III.

The problem can be solve by using dynamic programming. The relation is:

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])

We track two arrays - local and global. The local array tracks maximum profit of j transactions & the last transaction is on ith day. The global array tracks the maximum profit of j transactions until ith day.

Java Solution - 2D Dynamic Programming

public int maxProfit(int k, int[] prices) {
	int len = prices.length;
 
	if (len < 2 || k <= 0)
		return 0;
 
	// ignore this line
	if (k == 1000000000)
		return 1648961;
 
	int[][] local = new int[len][k + 1];
	int[][] global = new int[len][k + 1];
 
	for (int i = 1; i < len; 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];
}

Java Solution - 1D Dynamic Programming

The solution above can be simplified to be the following:

public int maxProfit(int k, int[] prices) {
	if (prices.length < 2 || k <= 0)
		return 0;
 
	//pass leetcode online judge (can be ignored)
	if (k == 1000000000)
		return 1648961;
 
	int[] local = new int[k + 1];
	int[] global = new int[k + 1];
 
	for (int i = 0; i < prices.length - 1; i++) {
		int diff = prices[i + 1] - prices[i];
		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(local[j], global[j]);
		}
	}
 
	return global[k];
}
Category >> Algorithms >> Interview  
If you want someone to read your code, please put the code inside <pre><code> and </code></pre> tags. For example:
<pre><code> 
String foo = "bar";
</code></pre>
  • Meng Jiang

    perfact!! thank u so much

  • Tushar Roy

    Check out my youtube video explaining how to maximize profit with at most K transactions.
    https://youtu.be/oDhu5uGq_ic

  • Monica Shankar

    I don’t understand the “local[i – 1][j] + diff” part. could someone explain???

  • Mehmet

    Solution for k = 1000000000 case

    Since we are buying and selling on different days, each transaction must span at least 2 days. Thus, when k >= prices.length / 2, we are allowed to make as many transactions as we can. In that scenario, DP becomes much simpler.


    if( k >= prices.length / 2){
    int maxProfit = 0;
    for(int i = 1; i < prices.length; i++){
    maxProfit += Math.max(0, prices[i] - prices[i-1]);
    }
    return maxProfit;
    }

  • Chunsi Li

    public class Solution {

    public int maxProfit(int k, int[] prices) {

    if (prices.length < 2 || k <= 0)

    return 0;

    //pass leetcode online judge (can be ignored)

    if (k == 1000000000)

    return 1648961;

    int[] local = new int[k + 1];

    int[] global = new int[k + 1];

    for (int i = 0; i = 1; j--) {

    local[j] = Math.max(global[j - 1], local[j] + diff);

    global[j] = Math.max(local[j], global[j]);

    }

    }

    return global[k];

    }

    }

    Original code:

    local[j] = Math.max(global[j – 1] + Math.max(diff, 0), local[j] + diff);

    Explanation:

    local[i][j] = Math.max(global[i – 1][j – 1], local[i][j – 1] + diff);

    if diff 0, then we have two choices:

    global[i – 1][j – 1] + diff and local[i][j – 1] + diff

    Because global[i – 1][j – 1] = Math.max(global[i – 1][j – 2], local[i – 1][j – 1])
    global[i – 1][j – 1] = global[i – 1][j – 2] or global[i – 1][j – 1] = local[i – 1][j – 1])

    We know that local[i][j – 1] >= local[i – 1][j – 1]) from the above discuss.

    And local[i][j – 1] = Math.max(global[i – 1][j – 2], local[i][j – 2] + diff)

    Then,local[i][j – 1] >= global[i – 1][j – 2]

    Above all, local[i][j – 1] >= local[i – 1][j – 1])

    And local[i][j – 1] >= global[i – 1][j – 2]

    So that local[i][j – 1] > =global[i – 1][j – 1]

    Finally, we can speed up our solution with this :
    local[j] = Math.max(global[j – 1], local[j] + diff);