Stock Buy and Sell with Transaction Fee
Last Updated :
04 Nov, 2025
Given an array arr[] denoting the cost of stock on each day and an integer k representing a transaction fee. Find the maximum total profit if we can buy and sell the stocks any number of times given that each transaction costs fee k.
Note: We can only sell a stock which we have bought earlier and we cannot hold multiple stocks on any day.
Examples:
Input: arr[] = [6, 1, 7, 2, 8, 4], k = 2
Output: 8
Explanation:
Buy the stock on day 2 and sell it on day 3 => 7 – 1 -2 = 4
Buy the stock on day 4 and sell it on day 5 => 8 – 2 - 2 = 4
Maximum Profit = 4 + 4 = 8
Input: arr[] = [7, 1, 5, 3, 6, 4], k = 1
Output: 5
Explanation:
Buy the stock on day 2 and sell it on day 3 => 5 – 1 - 1 = 3
Buy the stock on day 4 and sell it on day 5 => 6 – 3 - 1 = 2
Maximum Profit = 3 + 2 = 5
[Naive Approach] - Using Recursion - O(2n) Time and O(1) Space
The idea is to recursively generate all possible buy and sell combinations and compute the maximum among them. To do so, create a counter buy, which is 0 if no stock has been purchased else it is 1. Start from the 0th index, and for each index i, there are two possibilities:
- buy == 0: If no stock has been purchased, we can either skip the stock arr[i], or can purchase it by subtracting arr[i] from profit.
- buy == 1: If a stock has been purchased, we can't buy more and need to sell it. We can either sell it in current rate by adding arr[i] to profit and subtracting k of transaction fee, or skip to the next stock.
The maximum of this is the result.
C++
//Driver Code Starts
#include <iostream>
#include <vector>
using namespace std;
//Driver Code Ends
// recursive function to calculate the profit
int maxProfitRec(vector<int> &arr, int ind, int buy, int k) {
int n = arr.size();
// Base case
if (ind == n)
return 0;
int profit;
// if buy is 0, new stock can
// be purchased.
if (buy == 0) {
profit = max(maxProfitRec(arr, ind + 1, 0, k),
maxProfitRec(arr, ind + 1, 1, k) - arr[ind]);
}
// else stock can be sold
if (buy == 1) {
profit = max(maxProfitRec(arr, ind + 1, 1, k),
arr[ind] - k + maxProfitRec(arr, ind + 1, 0, k));
}
return profit;
}
int maxProfit(vector<int> &arr, int k) {
int n = arr.size();
return maxProfitRec(arr, 0, 0, k);
}
//Driver Code Starts
int main() {
vector<int> arr = {6, 1, 7, 2, 8, 4};
int k = 2;
cout << maxProfit(arr, k);
return 0;
}
//Driver Code Ends
Java
//Driver Code Starts
class GFG {
//Driver Code Ends
// Recursive function to calculate the profit
static int maxProfitRec(int[] arr,
int ind, int buy, int k) {
int n = arr.length;
// Base case
if (ind == n)
return 0;
int profit;
// if buy is 0, new stock can
// be purchased.
if (buy == 0) {
profit = Math.max(maxProfitRec(arr, ind + 1, 0, k),
maxProfitRec(arr, ind + 1, 1, k) - arr[ind]);
}
// else stock can be sold
else {
profit = Math.max(maxProfitRec(arr, ind + 1, 1, k),
arr[ind] - k + maxProfitRec(arr, ind + 1, 0, k));
}
return profit;
}
static int maxProfit(int[] arr, int k) {
int n = arr.length;
return maxProfitRec(arr, 0, 0, k);
}
//Driver Code Starts
public static void main(String[] args) {
int[] arr = {6, 1, 7, 2, 8, 4};
int k = 2;
System.out.println(maxProfit(arr, k));
}
}
//Driver Code Ends
Python
# Recursive function to calculate the profit
def maxProfitRec(arr, ind, buy, k):
n = len(arr)
# Base case
if ind == n:
return 0
# if buy is 0, new stock can
# be purchased.
if buy == 0:
profit = max(maxProfitRec(arr, ind + 1, 0, k),
maxProfitRec(arr, ind + 1, 1, k) - arr[ind])
# else stock can be sold
else:
profit = max(maxProfitRec(arr, ind + 1, 1, k),
arr[ind] - k + maxProfitRec(arr, ind + 1, 0, k))
return profit
def maxProfit(arr, k):
n = len(arr)
return maxProfitRec(arr, 0, 0, k)
if __name__ == "__main__":
#Driver Code Starts
arr = [6, 1, 7, 2, 8, 4]
k = 2
print(maxProfit(arr, k))
#Driver Code Ends
C#
//Driver Code Starts
using System;
class GFG {
//Driver Code Ends
// Recursive function to calculate the profit
static int maxProfitRec(int[] arr, int ind, int buy, int k) {
int n = arr.Length;
// Base case
if (ind == n)
return 0;
int profit;
// If buy is 0, new stock can be purchased
if (buy == 0) {
profit = Math.Max(maxProfitRec(arr, ind + 1, 0, k),
maxProfitRec(arr, ind + 1, 1, k) - arr[ind]);
}
// Else stock can be sold
else {
profit = Math.Max(maxProfitRec(arr, ind + 1, 1, k),
arr[ind] - k + maxProfitRec(arr, ind + 1, 0, k));
}
return profit;
}
// Function to calculate maximum profit
static int maxProfit(int[] arr, int k) {
int n = arr.Length;
return maxProfitRec(arr, 0, 0, k);
}
//Driver Code Starts
static void Main() {
int[] arr = {6, 1, 7, 2, 8, 4};
int k = 2;
Console.WriteLine(maxProfit(arr, k));
}
}
//Driver Code Ends
JavaScript
// Recursive function to calculate the profit
function maxProfitRec(arr, ind, buy, k) {
let n = arr.length;
// Base case
if (ind === n)
return 0;
let profit;
// if buy is 0, new stock can
// be purchased.
if (buy === 0) {
profit = Math.max(maxProfitRec(arr, ind + 1, 0, k),
maxProfitRec(arr, ind + 1, 1, k) - arr[ind]);
}
// else stock can be sold
else {
profit = Math.max(maxProfitRec(arr, ind + 1, 1, k),
arr[ind] - k + maxProfitRec(arr, ind + 1, 0, k));
}
return profit;
}
function maxProfit(arr, k) {
let n = arr.length;
return maxProfitRec(arr, 0, 0, k);
}
// Driver code
//Driver Code Starts
const arr = [6, 1, 7, 2, 8, 4];
const k = 2;
console.log(maxProfit(arr, k));
//Driver Code Ends
[Better Approach 1] - Using Memoization - O(n) Time and O(n) Space
The above approach can be optimized using memoization. The idea is to create a 2d array memo[][] of order n*2, where element memo[i][0] stores the maximum profit from day i to n-1 when no previous stock is pending and memo[i][1] stores maximum profit from day i to n-1 when there is previous stock remaining. For each recursive call, check if the sub-array is already computed, if so return the stored value else proceed as in above approach.
C++
//Driver Code Starts
#include <iostream>
#include <vector>
using namespace std;
//Driver Code Ends
// recursive function to calculate the profit
int maxProfitRec(vector<int> &arr, int ind,
int buy, int k, vector<vector<int>> &memo) {
int n = arr.size();
// Base case
if (ind == n)
return 0;
// Check if the result is already computed
if (memo[ind][buy] != -1)
return memo[ind][buy];
int profit;
// if buy is 0, new stock can
// be purchased.
if (buy == 0) {
profit = max(maxProfitRec(arr, ind + 1, 0, k, memo),
maxProfitRec(arr, ind + 1, 1, k, memo) - arr[ind]);
}
// else stock can be sold
if (buy == 1) {
profit = max(maxProfitRec(arr, ind + 1, 1, k, memo),
arr[ind] - k + maxProfitRec(arr, ind + 1, 0, k, memo));
}
return memo[ind][buy] = profit;
}
int maxProfit(vector<int> &arr, int k) {
int n = arr.size();
vector<vector<int>> memo(n, vector<int>(2, -1));
return maxProfitRec(arr, 0, 0, k, memo);
}
//Driver Code Starts
int main() {
vector<int> arr = {6, 1, 7, 2, 8, 4};
int k = 2;
cout << maxProfit(arr, k);
return 0;
}
//Driver Code Ends
Java
//Driver Code Starts
import java.util.Arrays;
class GFG {
//Driver Code Ends
// Recursive function to calculate the profit
static int maxProfitRec(int[] arr, int ind,
int buy, int k, int[][] memo) {
int n = arr.length;
// Base case
if (ind == n)
return 0;
// Check if the result is already computed
if (memo[ind][buy] != -1)
return memo[ind][buy];
int profit;
// if buy is 0, new stock can
// be purchased.
if (buy == 0) {
profit =
Math.max(maxProfitRec(arr, ind + 1, 0, k, memo),
maxProfitRec(arr, ind + 1, 1, k, memo) - arr[ind]);
}
// else stock can be sold
else {
profit =
Math.max(maxProfitRec(arr, ind + 1, 1, k, memo),
arr[ind] - k + maxProfitRec(arr, ind + 1, 0, k, memo));
}
return memo[ind][buy] = profit;
}
static int maxProfit(int[] arr, int k) {
int n = arr.length;
int[][] memo = new int[n][2];
for (int[] row : memo) {
Arrays.fill(row, -1);
}
return maxProfitRec(arr, 0, 0, k, memo);
}
//Driver Code Starts
public static void main(String[] args) {
int[] arr = {6, 1, 7, 2, 8, 4};
int k = 2;
System.out.println(maxProfit(arr, k));
}
}
//Driver Code Ends
Python
# Recursive function to calculate the profit
def maxProfitRec(arr, ind, buy, k, memo):
n = len(arr)
# Base case
if ind == n:
return 0
# Check if the result is already computed
if memo[ind][buy] != -1:
return memo[ind][buy]
# Calculate profit
if buy == 0:
profit = max(maxProfitRec(arr, ind + 1, 0, k, memo),
maxProfitRec(arr, ind + 1, 1, k, memo) - arr[ind])
else:
profit = max(maxProfitRec(arr, ind + 1, 1, k, memo),
arr[ind] - k + maxProfitRec(arr, ind + 1, 0, k, memo))
memo[ind][buy] = profit
return profit
def maxProfit(arr, k):
n = len(arr)
memo = [[-1 for _ in range(2)] for _ in range(n)]
return maxProfitRec(arr, 0, 0, k, memo)
if __name__ == "__main__":
#Driver Code Starts
arr = [6, 1, 7, 2, 8, 4]
k = 2
print(maxProfit(arr, k))
#Driver Code Ends
C#
//Driver Code Starts
using System;
class GFG {
//Driver Code Ends
// recursive function to calculate the profit
static int maxProfitRec(int[] arr, int ind,
int buy, int k, int[,] memo) {
int n = arr.Length;
// Base case
if (ind == n)
return 0;
// Check if the result is already computed
if (memo[ind, buy] != -1)
return memo[ind, buy];
int profit;
// if buy is 0, new stock can
// be purchased.
if (buy == 0) {
profit = Math.Max(maxProfitRec(arr, ind + 1, 0, k, memo),
maxProfitRec(arr, ind + 1, 1, k, memo) - arr[ind]);
}
// else stock can be sold
else {
profit = Math.Max(maxProfitRec(arr, ind + 1, 1, k, memo),
arr[ind] - k + maxProfitRec(arr, ind + 1, 0, k, memo));
}
memo[ind, buy] = profit;
return profit;
}
static int maxProfit(int[] arr, int k) {
int n = arr.Length;
int[,] memo = new int[n, 2];
for (int i = 0; i < n; i++) {
memo[i, 0] = -1;
memo[i, 1] = -1;
}
return maxProfitRec(arr, 0, 0, k, memo);
}
//Driver Code Starts
public static void Main(string[] args) {
int[] arr = {6, 1, 7, 2, 8, 4};
int k = 2;
Console.WriteLine(maxProfit(arr, k));
}
}
//Driver Code Ends
JavaScript
// recursive function to calculate the profit
function maxProfitRec(arr, ind, buy, k, memo) {
let n = arr.length;
// Base case
if (ind === n)
return 0;
// Check if the result is already computed
if (memo[ind][buy] !== -1)
return memo[ind][buy];
let profit;
// if buy is 0, new stock can
// be purchased.
if (buy === 0) {
profit = Math.max(maxProfitRec(arr, ind + 1, 0, k, memo),
maxProfitRec(arr, ind + 1, 1, k, memo) - arr[ind]);
}
// else stock can be sold
else {
profit = Math.max(maxProfitRec(arr, ind + 1, 1, k, memo),
arr[ind] - k + maxProfitRec(arr, ind + 1, 0, k, memo));
}
memo[ind][buy] = profit;
return profit;
}
function maxProfit(arr, k) {
let n = arr.length;
let memo = Array.from({ length: n },
() => Array(2).fill(-1));
return maxProfitRec(arr, 0, 0, k, memo);
}
// Driver Code
//Driver Code Starts
const arr = [6, 1, 7, 2, 8, 4];
const k = 2;
console.log(maxProfit(arr, k));
//Driver Code Ends
[Better Approach 2] - Using Tabulation - O(n) Time and O(n) Space
The idea is to use tabulation (bottom-up DP) approach and build the solution iteratively.
We create a 2D array dp[n + 1][2], where:
- n is the number of days.
- Each dp[i][buy] represents the maximum profit that can be earned starting from day i, given whether we are allowed to buy (buy = 0) or sell (buy = 1).
We fill this table in a bottom-up manner, starting from the last day and moving backward.
For each day i:
- If we can buy (buy == 0): We have two options — buy the stock and subtract its price from profit, or skip to the next day.
dp[i][0] = max(-arr[i] + dp[i + 1][1], dp[i + 1][0]) - If we can sell (buy == 1): We can either sell the stock (add price to profit and subtract transaction fee k) or skip to the next day.
dp[i][1] = max(arr[i] - k + dp[i + 1][0], dp[i + 1][1])
The base case is when we reach beyond the last index — profit is 0.
Finally, dp[0][0] gives the maximum profit possible starting from day 0 with the ability to buy.
C++
//Driver Code Starts
#include <iostream>
#include <vector>
using namespace std;
//Driver Code Ends
int maxProfit(vector<int> &arr, int k) {
int n = arr.size();
vector<vector<int>> dp(n+1, vector<int>(2, 0));
for (int ind = n - 1; ind >= 0; ind--) {
for (int buy = 0; buy <= 1; buy++) {
int profit;
// We can buy the stock
if (buy == 0) {
profit = max(dp[ind + 1][0],
dp[ind + 1][1] - arr[ind]);
}
// We can sell the stock
if (buy == 1) {
profit = max(dp[ind + 1][1],
arr[ind] - k + dp[ind + 1][0]);
}
dp[ind][buy] = profit;
}
}
// Return the maximum profit for buying.
return dp[0][0];
}
//Driver Code Starts
int main() {
vector<int> arr = {6, 1, 7, 2, 8, 4};
int k = 2;
cout << maxProfit(arr, k);
return 0;
}
//Driver Code Ends
Java
//Driver Code Starts
class GFG {
//Driver Code Ends
static int maxProfit(int[] arr, int k) {
int n = arr.length;
int[][] dp = new int[n + 1][2];
for (int ind = n - 1; ind >= 0; ind--) {
for (int buy = 0; buy <= 1; buy++) {
int profit;
// We can buy the stock
if (buy == 0) {
profit = Math.max(dp[ind + 1][0],
dp[ind + 1][1] - arr[ind]);
}
// We can sell the stock
else {
profit = Math.max(dp[ind + 1][1],
arr[ind] - k + dp[ind + 1][0]);
}
dp[ind][buy] = profit;
}
}
// Return the maximum profit for buying.
return dp[0][0];
}
//Driver Code Starts
public static void main(String[] args) {
int[] arr = {6, 1, 7, 2, 8, 4};
int k = 2;
System.out.println(maxProfit(arr, k));
}
}
//Driver Code Ends
Python
def maxProfit(arr, k):
n = len(arr)
dp = [[0 for _ in range(2)] for _ in range(n + 1)]
for ind in range(n - 1, -1, -1):
for buy in range(2):
# We can buy the stock
if buy == 0:
profit = max(dp[ind + 1][0],
dp[ind + 1][1] - arr[ind])
# We can sell the stock
else:
profit = max(dp[ind + 1][1],
arr[ind] - k + dp[ind + 1][0])
dp[ind][buy] = profit
# Return the maximum profit for buying.
return dp[0][0]
if __name__ == "__main__":
#Driver Code Starts
arr = [6, 1, 7, 2, 8, 4]
k = 2
print(maxProfit(arr, k))
#Driver Code Ends
C#
//Driver Code Starts
using System;
class GFG {
//Driver Code Ends
static int maxProfit(int[] arr, int k) {
int n = arr.Length;
int[,] dp = new int[n + 1, 2];
for (int ind = n - 1; ind >= 0; ind--) {
for (int buy = 0; buy <= 1; buy++) {
int profit;
// We can buy the stock
if (buy == 0) {
profit = Math.Max(dp[ind + 1, 0],
dp[ind + 1, 1] - arr[ind]);
}
// We can sell the stock
else {
profit = Math.Max(dp[ind + 1, 1],
arr[ind] - k + dp[ind + 1, 0]);
}
dp[ind, buy] = profit;
}
}
// Return the maximum profit for buying.
return dp[0, 0];
}
//Driver Code Starts
static void Main(string[] args) {
int[] arr = {6, 1, 7, 2, 8, 4};
int k = 2;
Console.WriteLine(maxProfit(arr, k));
}
}
//Driver Code Ends
JavaScript
function maxProfit(arr, k) {
const n = arr.length;
const dp = Array.from({ length: n + 1 }, () => [0, 0]);
for (let ind = n - 1; ind >= 0; ind--) {
for (let buy = 0; buy <= 1; buy++) {
let profit;
// We can buy the stock
if (buy === 0) {
profit = Math.max(dp[ind + 1][0],
dp[ind + 1][1] - arr[ind]);
}
// We can sell the stock
else {
profit = Math.max(dp[ind + 1][1],
arr[ind] - k + dp[ind + 1][0]);
}
dp[ind][buy] = profit;
}
}
// Return the maximum profit for buying.
return dp[0][0];
}
// Driver Code
//Driver Code Starts
const arr = [6, 1, 7, 2, 8, 4];
const k = 2;
console.log(maxProfit(arr, k));
//Driver Code Ends
[Expected Approach] Space Optimized - O(n) Time and O(1) Space
Instead of using a DP table, we observe that each day’s profit depends only on the next day’s states.
So, we keep two variables:
- noStock – profit when not holding a stock
- inHand – profit when holding a stock
For each day (starting from the end):
- To buy, choose between skipping or buying today → newNoStock = max(noStock, inHand - arr[i])
- To sell, choose between skipping or selling today (paying fee k) → newInHand = max(inHand, arr[i] - k + noStock)
Update both states for the next iteration. Finally, noStock holds the maximum achievable profit.
C++
//Driver Code Starts
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//Driver Code Ends
int maxProfit(vector<int> &arr, int k) {
int n = arr.size();
int noStock = 0, inHand = 0;
for (int i = n - 1; i >= 0; i--) {
// Choose to buy or skip
int newNoStock = max(noStock, inHand - arr[i]);
// Choose to sell or skip
int newInHand = max(inHand, arr[i] - k + noStock);
// Update states
noStock = newNoStock;
inHand = newInHand;
}
return noStock;
}
//Driver Code Starts
int main() {
vector<int> arr = {6, 1, 7, 2, 8, 4};
int k = 2;
cout << maxProfit(arr, k);
return 0;
}
//Driver Code Ends
Java
//Driver Code Starts
import java.util.ArrayList;
import java.util.Arrays;
class GFG {
//Driver Code Ends
static int maxProfit(int[] arr, int k) {
int n = arr.length;
int noStock = 0, inHand = 0;
for (int i = n - 1; i >= 0; i--) {
// Choose to buy or skip
int newNoStock = Math.max(noStock, inHand - arr[i]);
// Choose to sell or skip
int newInHand = Math.max(inHand, arr[i] - k + noStock);
// Update states
noStock = newNoStock;
inHand = newInHand;
}
return noStock;
}
//Driver Code Starts
public static void main(String[] args) {
int[] arr = {6, 1, 7, 2, 8, 4};
int k = 2;
System.out.println(maxProfit(arr, k));
}
}
//Driver Code Ends
Python
def maxProfit(arr, k):
n = len(arr)
noStock, inHand = 0, 0
for i in range(n - 1, -1, -1):
# Choose to buy or skip
newNoStock = max(noStock, inHand - arr[i])
# Choose to sell or skip
newInHand = max(inHand, arr[i] - k + noStock)
# Update states
noStock, inHand = newNoStock, newInHand
return noStock
if __name__ == '__main__':
#Driver Code Starts
arr = [6, 1, 7, 2, 8, 4]
k = 2
print(maxProfit(arr, k))
#Driver Code Ends
C#
//Driver Code Starts
using System;
using System.Collections.Generic;
class GFG {
//Driver Code Ends
static int maxProfit(int[] arr, int k) {
int n = arr.Length;
int noStock = 0, inHand = 0;
for (int i = n - 1; i >= 0; i--) {
// Choose to buy or skip
int newNoStock = Math.Max(noStock, inHand - arr[i]);
// Choose to sell or skip
int newInHand = Math.Max(inHand, arr[i] - k + noStock);
// Update states
noStock = newNoStock;
inHand = newInHand;
}
return noStock;
}
//Driver Code Starts
static void Main() {
int[] arr = {6, 1, 7, 2, 8, 4};
int k = 2;
Console.WriteLine(maxProfit(arr, k));
}
}
//Driver Code Ends
JavaScript
function maxProfit(arr, k) {
const n = arr.length;
let noStock = 0, inHand = 0;
for (let i = n - 1; i >= 0; i--) {
// Choose to buy or skip
const newNoStock = Math.max(noStock, inHand - arr[i]);
// Choose to sell or skip
const newInHand = Math.max(inHand, arr[i] - k + noStock);
// Update states
noStock = newNoStock;
inHand = newInHand;
}
return noStock;
}
// Driver Code
//Driver Code Starts
const arr = [6, 1, 7, 2, 8, 4];
const k = 2;
console.log(maxProfit(arr, k));
//Driver Code Ends
Explore
DSA Fundamentals
Data Structures
Algorithms
Advanced
Interview Preparation
Practice Problem