Maximum profit by buying and selling a share at most k times

In share trading, a buyer buys shares and sells on future date. Given stock price of n days, the trader is allowed to make at most k transactions, where new transaction can only start after previous transaction is complete, find out maximum profit that a share trader could have made.

Input:  
Price = [10, 22, 5, 75, 65, 80]
    K = 2
Output:  87
Trader earns 87 as sum of 12 and 75
Buy at price 10, sell at 22, buy at 
5 and sell at 80

Input:  
Price = [12, 14, 17, 10, 14, 13, 12, 15]
    K = 3
Output:  12
Trader earns 12 as sum of 5, 4 and 3
Buy at price 12, sell at 17, buy at 10 
and sell at 14 and buy at 12 and sell
at 15
 
Input:  
Price = [100, 30, 15, 10, 8, 25, 80]
    K = 3
Output:  72
Only one transaction. Buy at price 8 
and sell at 80.

Input:  
Price = [90, 80, 70, 60, 50]
    K = 1
Output:  0
Not possible to earn. 

There are various versions of the problem. If we are allowed to buy and sell only once, then we can use Maximum difference between two elements algorithm. If we are allowed to make at most 2 transactions, we can follow approach discussed here. If we are allowed to buy and sell any number of times, we can follow approach discussed here.



In this post, we are only allowed to make at max k transactions. The problem can be solve by using dynamic programming.

Let profit[t][i] represent maximum profit using at most t transactions up to day i (including day i). Then the relation is:

profit[t][i] = max(profit[t][i-1], max(price[i] – price[j] + profit[t-1][j]))
          for all j in range [0, i-1]

profit[t][i] will be maximum of –

  1. profit[t][i-1] which represents not doing any transaction on the ith day.
  2. Maximum profit gained by selling on ith day. In order to sell shares on ith day, we need to purchase it on any one of [0, i – 1] days. If we buy shares on jth day and sell it on ith day, max profit will be price[i] – price[j] + profit[t-1][j] where j varies from 0 to i-1. Here profit[t-1][j] is best we could have done with one less transaction till jth day.

Below is Dynamic Programming based implementation.

C++

// C++ program to find out maximum profit by
// buying and selling a share atmost k times
// given stock price of n days
#include <climits>
#include <iostream>
using namespace std;

// Function to find out maximum profit by buying
// & selling a share atmost k times given stock
// price of n days
int maxProfit(int price[], int n, int k)
{
    // table to store results of subproblems
    // profit[t][i] stores maximum profit using
    // atmost t transactions up to day i (including
    // day i)
    int profit[k + 1][n + 1];

    // For day 0, you can't earn money
    // irrespective of how many times you trade
    for (int i = 0; i <= k; i++)
        profit[i][0] = 0;

    // profit is 0 if we don't do any transation
    // (i.e. k =0)
    for (int j = 0; j <= n; j++)
        profit[0][j] = 0;

    // fill the table in bottom-up fashion
    for (int i = 1; i <= k; i++) {
        for (int j = 1; j < n; j++) {
            int max_so_far = INT_MIN;

            for (int m = 0; m < j; m++)
                max_so_far = max(max_so_far,
                                 price[j] - price[m] + profit[i - 1][m]);

            profit[i][j] = max(profit[i][j - 1], max_so_far);
        }
    }

    return profit[k][n - 1];
}

// Driver code
int main()
{
    int k = 2;
    int price[] = { 10, 22, 5, 75, 65, 80 };
    int n = sizeof(price) / sizeof(price[0]);

    cout << "Maximum profit is: "
         << maxProfit(price, n, k);

    return 0;
}

Java

// Java program to find out maximum 
// profit by buying and selling a
// share atmost k times given
// stock price of n days

class GFG {
    
    // Function to find out 
    // maximum profit by 
    // buying & selling a 
    // share atmost k times
    // given stock price of n days
    static int maxProfit(int[] price, 
                         int n, 
                         int k)
    {
        
        // table to store results
        // of subproblems
        // profit[t][i] stores 
        // maximum profit using 
        // atmost t transactions up
        // to day i (including day i)
        int[][] profit = new int[k + 1][n + 1];

        // For day 0, you can't 
        // earn money irrespective
        // of how many times you trade
        for (int i = 0; i <= k; i++)
            profit[i][0] = 0;

        // profit is 0 if we don't
        // do any transation
        // (i.e. k =0)
        for (int j = 0; j <= n; j++)
            profit[0][j] = 0;

        // fill the table in 
        // bottom-up fashion
        for (int i = 1; i <= k; i++) 
        {
            for (int j = 1; j < n; j++)
            {
                int max_so_far = 0;

                for (int m = 0; m < j; m++)
                max_so_far = Math.max(max_so_far, price[j] -
                             price[m] + profit[i - 1][m]);

                profit[i][j] = Math.max(profit[i] [j - 1], 
                                              max_so_far);
            }
        }

        return profit[k][n - 1];
    }

    // Driver code 
    public static void main(String []args)
    {
        int k = 2;
        int[] price = { 10, 22, 5, 75, 65, 80 };
        int n = price.length;
        System.out.println("Maximum profit is: " + 
                            maxProfit(price, n, k));
    }
}

// This code is contributed by Anshul Aggarwal.

C#

// C# program to find out maximum profit by
// buying and selling a share atmost k times
// given stock price of n days
using System;

class GFG {
    
    // Function to find out maximum profit by 
    // buying & selling/ a share atmost k times
    // given stock price of n days
    static int maxProfit(int[] price, int n, int k)
    {
        // table to store results of subproblems
        // profit[t][i] stores maximum profit using atmost
        // t transactions up to day i (including day i)
        int[, ] profit = new int[k + 1, n + 1];

        // For day 0, you can't earn money
        // irrespective of how many times you trade
        for (int i = 0; i <= k; i++)
            profit[i, 0] = 0;

        // profit is 0 if we don't do any transation
        // (i.e. k =0)
        for (int j = 0; j <= n; j++)
            profit[0, j] = 0;

        // fill the table in bottom-up fashion
        for (int i = 1; i <= k; i++) {
            for (int j = 1; j < n; j++) {
                int max_so_far = 0;

                for (int m = 0; m < j; m++)
                max_so_far = Math.Max(max_so_far, price[j] -
                               price[m] + profit[i - 1, m]);

                profit[i, j] = Math.Max(profit[i, j - 1], max_so_far);
            }
        }

        return profit[k, n - 1];
    }

    // Driver code to test above
    public static void Main()
    {
        int k = 2;
        int[] price = { 10, 22, 5, 75, 65, 80 };

        int n = price.Length;

        Console.Write("Maximum profit is: " + 
                     maxProfit(price, n, k));
    }
}

// This code is contributed by Sam007

PHP


<?php
// PHP program to find out maximum profit by
// buying and selling a share atmost k times
// given stock price of n days

// Function to find out maximum profit by buying
// & selling a share atmost k times given stock
// price of n days
function maxProfit($price, $n, $k)
{
    
    // table to store results of subproblems
    // profit[t][i] stores maximum profit using
    // atmost t transactions up to day i (including
    // day i)
    $profit[$k + 1][$n + 1] = 0;
    
    // For day 0, you can't earn money
    // irrespective of how many times you trade
    for ($i = 0; $i <= $k; $i++)
        $profit[$i][0] = 0;

    // profit is 0 if we don't
    // do any transation
    // (i.e. k =0)
    for ($j = 0; $j <= $n; $j++)
        $profit[0][$j] = 0;

    // fill the table in 
    // bottom-up fashion
    for ($i = 1; $i <= $k; $i++) {
        for ($j = 1; $j < $n; $j++) {
            $max_so_far = PHP_INT_MIN;

            for ($m = 0; $m < $j; $m++)
                $max_so_far = max($max_so_far, 
                              $price[$j] - $price[$m] +
                              $profit[$i - 1][$m]);

            $profit[$i][$j] = max($profit[$i][$j - 1],
                                         $max_so_far);
        }
    }

    return $profit[$k][$n - 1];
}

    // Driver code
    $k = 2;
    $price = array (10, 22, 5, 75, 65, 80 );
    $n = sizeof($price);
    echo "Maximum profit is: ". maxProfit($price, $n, $k);

// This is contributed by mits
?>

Output :

Maximum profit is: 87

Optimized Solution:
The above solution has time complexity of O(k.n2). It can be reduced if we are able to calculate maximum profit gained by selling shares on ith day in constant time.

profit[t][i] = max(profit [t][i-1], max(price[i] – price[j] + profit[t-1][j]))
                            for all j in range [0, i-1]

If we carefully notice,
max(price[i] – price[j] + profit[t-1][j])
for all j in range [0, i-1]

can be rewritten as,
= price[i] + max(profit[t-1][j] – price[j])
for all j in range [0, i-1]
= price[i] + max(prevDiff, profit[t-1][i-1] – price[i-1])
where prevDiff is max(profit[t-1][j] – price[j])
for all j in range [0, i-2]

So, if we have already calculated max(profit[t-1][j] – price[j]) for all j in range [0, i-2], we can calculate it for j = i – 1 in constant time. In other words, we don’t have to look back in range [0, i-1] anymore to find out best day to buy. We can determine that in constant time using below revised relation.

profit[t][i] = max(profit[t][i-1], price[i] + max(prevDiff, profit [t-1][i-1] – price[i-1])
where prevDiff is max(profit[t-1][j] – price[j]) for all j in range [0, i-2]

Below is its optimized implementation –

C++

// C++ program to find out maximum profit by buying
// and/ selling a share atmost k times given stock
// price of n days
#include <climits>
#include <iostream>
using namespace std;

// Function to find out maximum profit by buying &
// selling/ a share atmost k times given stock price
// of n days
int maxProfit(int price[], int n, int k)
{
    // table to store results of subproblems
    // profit[t][i] stores maximum profit using atmost
    // t transactions up to day i (including day i)
    int profit[k + 1][n + 1];

    // For day 0, you can't earn money
    // irrespective of how many times you trade
    for (int i = 0; i <= k; i++)
        profit[i][0] = 0;

    // profit is 0 if we don't do any transation
    // (i.e. k =0)
    for (int j = 0; j <= n; j++)
        profit[0][j] = 0;

    // fill the table in bottom-up fashion
    for (int i = 1; i <= k; i++) {
        int prevDiff = INT_MIN;
        for (int j = 1; j < n; j++) {
            prevDiff = max(prevDiff,
                           profit[i - 1][j - 1] - price[j - 1]);
            profit[i][j] = max(profit[i][j - 1],
                               price[j] + prevDiff);
        }
    }

    return profit[k][n - 1];
}

// Driver Code
int main()
{
    int k = 3;
    int price[] = { 12, 14, 17, 10, 14, 13, 12, 15 };

    int n = sizeof(price) / sizeof(price[0]);

    cout << "Maximum profit is: "
         << maxProfit(price, n, k);

    return 0;
}

Java

// Java program to find out maximum
// profit by buying and selling a
// share atmost k times given stock
// price of n days
import java.io.*;

class GFG {
    
    // Function to find out maximum profit by
    // buying & selling/ a share atmost k times 
    // given stock price of n days
    static int maxProfit(int price[], 
                         int n, int k)
    {
        
        // table to store results of subproblems
        // profit[t][i] stores maximum profit
        // using atmost t transactions up to day
        // i (including day i)
        int profit[][] = new int[k + 1][ n + 1];

        // For day 0, you can't earn money
        // irrespective of how many times you trade
        for (int i = 0; i <= k; i++)
            profit[i][0] = 0;

        // profit is 0 if we don't do any 
        // transation (i.e. k =0)
        for (int j = 0; j <= n; j++)
            profit[0][j] = 0;

        // fill the table in bottom-up fashion
        for (int i = 1; i <= k; i++) 
        {
            int prevDiff = Integer.MIN_VALUE;
            for (int j = 1; j < n; j++) 
            {
                prevDiff = Math.max(prevDiff, 
                           profit[i - 1][j - 1] - 
                           price[j - 1]);
                profit[i][j] = Math.max(profit[i][j - 1], 
                               price[j] + prevDiff);
            }
        }

        return profit[k][n - 1];
    }

// Driver code
public static void main (String[] args) 
    {
        int k = 3;
        int price[] = {12, 14, 17, 10, 14, 13, 12, 15};

        int n = price.length;

        System.out.println("Maximum profit is: " + 
                            maxProfit(price, n, k));
    }
} 

// This code is contributed by Sam007

C#

// C# program to find out maximum profit by buying
// and selling a share atmost k times given stock
// price of n days
using System;

class GFG {
    
    // Function to find out maximum profit by
    // buying & selling/ a share atmost k times 
    // given stock price of n days
    static int maxProfit(int[] price, int n, int k)
    {
        // table to store results of subproblems
        // profit[t][i] stores maximum profit using atmost
        // t transactions up to day i (including day i)
        int[, ] profit = new int[k + 1, n + 1];

        // For day 0, you can't earn money
        // irrespective of how many times you trade
        for (int i = 0; i <= k; i++)
            profit[i, 0] = 0;

        // profit is 0 if we don't do any transation
        // (i.e. k =0)
        for (int j = 0; j <= n; j++)
            profit[0, j] = 0;

        // fill the table in bottom-up fashion
        for (int i = 1; i <= k; i++) {
            int prevDiff = int.MinValue;
            for (int j = 1; j < n; j++) {
            prevDiff = Math.Max(prevDiff,
                            profit[i - 1, j - 1] - price[j - 1]);
            profit[i, j] = Math.Max(profit[i, j - 1],
                                price[j] + prevDiff);
            }
        }

        return profit[k, n - 1];
    }

    // Driver code to test above
    public static void Main()
    {
        int k = 3;
        int[] price = {12, 14, 17, 10, 14, 13, 12, 15};

        int n = price.Length;

        Console.Write("Maximum profit is: " + 
                     maxProfit(price, n, k));
    }
}

// This code is contributed by Sam007

PHP

<?php
// PHP program to find out maximum
// profit by buying and selling a 
// share atmost k times given stock
// price of n days

// Function to find out maximum
// profit by buying & selling a 
// share atmost k times given 
// stock price of n days
function maxProfit($price, $n, $k)
{
    
    // table to store results 
    // of subproblems profit[t][i]
    // stores maximum profit using
    // atmost t transactions up to
    // day i (including day i)
    $profit[$k + 1][$n + 1]=0;

    // For day 0, you can't 
    // earn money irrespective
    // of how many times you trade
    for ($i = 0; $i <= $k; $i++)
        $profit[$i][0] = 0;

    // profit is 0 if we don't
    // do any transation
    // (i.e. k =0)
    for ($j = 0; $j <= $n; $j++)
        $profit[0][$j] = 0;

    // fill the table in
    // bottom-up fashion
    $prevDiff = NULL;
    for ($i = 1; $i <= $k; $i++) {
        for ($j = 1; $j < $n; $j++) {
            $prevDiff = max($prevDiff, $profit[$i - 1][$j - 1] - 
                                               $price[$j - 1]);
            $profit[$i][$j] = max($profit[$i][$j - 1],
                              $price[$j] + $prevDiff);
        }
    }
    return $profit[$k][$n - 1];
}

    // Driver Code
    $k = 3;
    $price = array(12, 14, 17, 10, 
                   14, 13, 12, 15);
    $n = sizeof($price);
    echo "Maximum profit is: "
         , maxProfit($price, $n, $k);

// This code is contributed by nitin mittal
?>


Output :

Maximum profit is: 12

Time complexity of above solution is O(kn) and space complexity is O(nk). Space complexity can further be reduced to O(n) as we uses the result from last transaction. But to make the article easily readable, we have used O(kn) space.

This article is contributed by Aditya Goel. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above






Recommended Posts:



4.5 Average Difficulty : 4.5/5.0
Based on 91 vote(s)