Best Time to Buy Sell Stock Q&A

Why is this problem tagged with “Dynamic programming”?

Dynamic programming is a method for solving complex problems by breaking them down into simpler subproblems, solving each of those subproblems just once, and storing their solutions using a memory-based data structure (array, map, etc). Each of the subproblem solutions is indexed in some way, typically based on the values of its input parameters, so as to facilitate its lookup. Thus, the “dynamic” part of “dynamic programming” comes from this process of using previous results to make solving the next subproblem easier.

The stock trading problem here is considered a dynamic programming problem because it involves finding an optimal solution (maximum profit) by making decisions based on previous states (lowest price seen so far, and the maximum profit calculated so far).

In the process of iterating through the prices array, we’re essentially breaking down the overall problem of “find the maximum possible profit” into a series of subproblems: “what’s the maximum profit if we sell on this day?”, considering each day one by one.

We then ‘remember’ the results of these subproblems - the maximum profit so far and the lowest price so far - and use these results to help solve the next subproblem. This concept of using previously computed information to solve the next problem is the core idea behind dynamic programming, and this is why this problem is categorized as a dynamic programming problem.

Yes, you are correct. Kadane’s algorithm is indeed a form of dynamic programming, and it can be applied to solve this problem.

Kadane’s algorithm is used for finding the maximum sum subarray in an array. This problem can be transformed to align with the idea of Kadane’s algorithm, where instead of finding the maximum sum subarray, we find the maximum difference between elements in the array.

In this problem, the dynamic programming concept comes into play as we’re essentially trying to find the maximum difference (maximum profit) between prices[i] (selling price) and the minimum price seen so far (buying price), where the selling date is after the buying date. The “current state” depends on the “previous state” which aligns with the dynamic programming’s core idea.

The reason it’s classified as dynamic programming is because you’re storing the minimum price seen so far and the maximum profit seen so far while traversing through the array. The maximum profit seen so far is calculated using the minimum price seen so far, and the value of the current element. So, this problem is about making optimal decisions based on the results of previous decisions, a key trait of dynamic programming problems.

However, it’s worth mentioning that this problem is quite simple and can be solved using a single pass through the array, which does not fully demonstrate the complexities and nuances typically associated with dynamic programming problems.

prices = [2, 4, 1]

Output: 0 Expected: 2

You buy on day three but cannot sell because it is the last day. Should that not be zero?

You may have misunderstood the order of operations. According to the problem statement, you should aim to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock.

Given the array prices = [2, 4, 1], the optimal solution would be:

  • Buy on the first day when the price is 2.
  • Sell on the second day when the price is 4.

The profit from this transaction would be 4 - 2 = 2. Therefore, the expected output would be 2, not 0.

If you bought on the third day when the price is 1, you would not have a future day to sell it, thus no profit can be made from this transaction. But the problem asks for the maximum profit you can achieve from this transaction. So we don’t have to consider the case where we buy on the last day as it will not yield any profit.

the approach i took is: find the minimum element and then maxi=mini then use a loop from the next index of the lowest mini element and then find maxi, then return the output.

Your approach seems to be finding the minimum element, assuming that’s the optimal point to buy, and then finding the maximum element after that point, assuming that’s the optimal point to sell. However, this approach can fail in certain situations.

Consider this example: prices = [3,2,6,5,0,3].

The minimum element is 0, which is at the 5th index (0-based index). However, if you start from the next index (6th), there are no more elements, and hence you can’t find a selling price. So, the maximum profit according to your method would be 0, which is not correct.

The correct approach is to iterate through the array, keeping track of the minimum price and the maximum profit so far. This way, you are considering the scenario where you sell at every possible day, and hence you are sure to find the maximum profit.

Here is the Python code for this approach:

1
2
3
4
5
6
7
def maxProfit(prices):
    min_price = float('inf')
    max_profit = 0
    for price in prices:
        min_price = min(min_price, price)
        max_profit = max(max_profit, price - min_price)
    return max_profit

This way, you always consider selling the stock at every given day and ensure that you are maximizing the profit. It’s essentially a ‘running’ minimum and maximum calculation.

you have to maintain your profit in a variable and only change the variable if the new profit is greater than the previous one, so for this scenario, 2 is the former profit, 0 is the new one, it is not greater than 2 so you don’t change your profit.

This approach is also referred to as maintaining a “running maximum”. The idea is to always track the maximum profit (or minimum cost) so far while traversing the array, and only update this value when you find a higher profit (or lower cost).

In the context of the stock trading problem, the algorithm would be keeping track of the lowest buying price (minPrice) and the maximum possible profit (maxProfit) seen so far. As we iterate through the prices array:

  1. If the current price is lower than minPrice, we update minPrice with the current price, as this would be a more profitable day to buy the stock.

  2. If selling at the current price would yield a higher profit than maxProfit (i.e., if currentPrice - minPrice > maxProfit), we update maxProfit.

By the end of the array, maxProfit will hold the maximum possible profit from a single transaction.

This way, even if we encounter a day where selling the stock would result in zero or negative profit, it doesn’t affect our maxProfit variable as long as there has been a previous day that offered a higher profit.

What I did was look at what the largest value after i is for each i, and what the smallest value is before each i. Then, for each i, i subtract smallest from largest. This is your optimal profit for buying before i and selling after i. Now you just find the largest number out of these, and you’re done.

Your approach is correct, and it will work. However, it is not optimal in terms of time complexity. The time complexity of your approach is O(n^2) because for each day, you are scanning all the subsequent days to find the maximum price, and all the previous days to find the minimum price.

A more optimal solution would be using a single pass (O(n)) solution. This would involve keeping track of the minimum price so far and the maximum profit that can be made.

Here’s the Python code for it:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def maxProfit(prices):
    minPrice = float('inf')
    maxProfit = 0
   
    for price in prices:
        if price < minPrice:
            minPrice = price
        elif price - minPrice > maxProfit:
            maxProfit = price - minPrice
   
    return maxProfit

In this approach, we start by initializing minPrice as infinity and maxProfit as 0. Then we iterate through the array. For each price, we do the following:

  1. If the price is less than minPrice, we update minPrice to the current price. This represents the lowest price we have seen so far.
  2. If the difference between the current price and minPrice is greater than maxProfit, we update maxProfit. This represents the maximum profit we can make by buying at the lowest price seen so far and selling at the current price.

After going through all the prices, we return maxProfit which represents the maximum profit we can make from one transaction.

This approach only requires one pass through the data and maintains constant space complexity, making it more efficient than scanning for max and min prices around each day.

Actually, the idea here is how you can make the maximum of profits. You don’t have to buy the stock when it’s at its lowest price. Here you can buy the first day and sell the second day and still make a profit which is 2.

Exactly, the goal is to maximize the profit, and for that, you don’t necessarily need to buy the stock at its lowest price and sell it at its highest price.

The rule is that you need to buy before you sell, so you are looking for a pair (i, j) where i < j and prices[j] - prices[i] is as large as possible.

So, in the example you gave, with prices = [2, 4, 1], you can buy on the first day when the price is 2 and sell on the second day when the price is 4, making a profit of 2.

This is exactly what the optimized approach I described in the previous post does. It goes through the array of prices and for each price, it calculates the profit that could be made by selling at that price (assuming you bought at the lowest price seen so far). It then updates the maximum profit seen so far.

How to get max profit 4 from input [3,2,6,5,0,3]?

Let’s step through the array:

  1. On the first day, the price is 3. You could buy the stock, but there’s no way to know yet if this is the best decision.

  2. On the second day, the price drops to 2. If you bought the stock on the first day, you would be at a loss. But if you didn’t buy on the first day, this would be the best day to buy so far.

  3. On the third day, the price jumps to 6. If you bought the stock on the second day for 2, you could sell it today for a profit of 6 - 2 = 4. This is the highest profit possible so far.

  4. On the fourth day, the price drops to 5. There’s no opportunity for more profit here.

  5. On the fifth day, the price drops further to 0. If you haven’t sold yet, this would be the best day to buy so far. But if you did sell on the third day, you already made the highest possible profit, and buying again now wouldn’t help.

  6. On the sixth day, the price goes back up to 3. If you bought on the fifth day, you could sell today for a profit of 3. But this is less than the profit of 4 you could have made by buying on the second day and selling on the third day.

So, the maximum profit you can make from the price sequence [3,2,6,5,0,3] is 4, by buying on the second day when the price is 2 and selling on the third day when the price is 6.

3 (buy), 2 (buy) , 6 (sell), 5 (hold), 0 (hold), 3 (hold) -3 -2 + (2*6) = -5 + 12 = 7

I believe there’s a misunderstanding here. In this problem statement, you can only perform one buy-sell operation, not multiple. So you cannot buy twice before you sell, as you have done on the first and second days in your example.

The challenge is to find one pair of “buy” and “sell” days that maximizes your profit. This means you need to buy at the lowest price and sell at the highest price that occurs after the buy.

Here’s the correct sequence based on your list:

  • Day 1: Price is 3. You could buy, but it’s not the lowest price.
  • Day 2: Price is 2. You buy.
  • Day 3: Price is 6. You sell. This gives a profit of 6 - 2 = 4.
  • Day 4: Price is 5. You do nothing because you’ve already sold.
  • Day 5: Price is 0. You do nothing because you’ve already sold.
  • Day 6: Price is 3. You do nothing because you’ve already sold.

So the maximum profit you can get from this sequence is 4.

isn’t ‘0’ a buy_price ??…and its smallest too.

Yes, you’re correct that ‘0’ is the smallest price and would be the most beneficial to buy at. However, the catch here is that we can’t sell the stock after the last day. In this case, ‘0’ is on the last day of the given price array, so even though it’s the cheapest price, buying on that day wouldn’t yield any profit because we couldn’t sell it afterwards.

The rule is that we need to buy the stock at a certain price and then sell it at a later date. This is why we couldn’t choose ‘0’ as the buying price in this specific scenario, even though it’s the smallest number.

This is why we select ‘2’ as the buying price and ‘6’ as the selling price, as that gives the maximum profit under the constraints. If we were allowed to hold the stock past the given price array, then ‘0’ would indeed be the best price to buy at. But with the given constraints, we can’t sell after buying at ‘0’, and thus it can’t contribute to our profit.

One thing I noticed in this problem is that we go from left to right (which captures the time element). Buy now, sell later is a invariant that you cannot violate. You scan from left to right and keep looking for the best profit.

Yes, you’re absolutely correct! This problem indeed utilizes a left-to-right scan of the array which is representative of time progression. This is a crucial aspect of the problem since it dictates the direction in which you can make transactions. You can only sell a stock after you have bought it, which in terms of this array representation means you can only sell at positions to the right of where you bought.

So, the solution involves scanning through the array from left to right and at each position considering whether we should “buy” the stock at the current price. This is achieved by tracking the minimum price (minPrice) seen so far. Then, we also need to decide whether we should “sell” at the current price by calculating the potential profit (current price - minPrice) and updating our maxProfit if this profit is greater than what we’ve seen before.

By doing this continuous left-to-right scanning and updating of our minPrice and maxProfit, we ensure that our solution is always adhering to the “buy now, sell later” rule and that it correctly identifies the maximum possible profit.

I solved the problem using dynamic programming (iteratively) but I am trying to draw the recursive tree. Since I am trying to understand DP as well as possible. I failed though so can someone help?

Also is there a way to solve this using memoization (recursively). I tried and failed as well.

The “maximum profit” problem can be a bit tricky to visualize with a traditional decision tree or recursive tree, as you typically would with many dynamic programming problems, because you’re essentially making only one decision: to buy or sell at each point in time. However, it’s still possible to draw a type of “decision line” to represent the choices made.

Here is a simple way to understand it:

Imagine each day as a node on a line (not a tree). The line goes from left to right (day 1 to day N). On each day (node), you have two options - buy or sell (given that you’ve bought a stock before you sell). Each of these choices will lead you to the next day (node).

For instance, consider the array [7,1,5,3,6,4]:

Day 1 - You can buy at 7 or do nothing. Day 2 - If you bought on Day 1, you can sell at 1 (not a good idea) or hold. If you did nothing on Day 1, you can buy at 1. Day 3 - Depending on what you did on Day 2, you can choose to sell at 5 or hold/buy. …and so on.

As for a recursive solution, you could potentially use a top-down approach, but it may not be as efficient or straightforward as the iterative solution. Here’s a rough idea:

  1. Define a recursive function that takes the current day and a boolean indicating whether you own a stock as arguments.
  2. If you’re at the end of the prices array, return 0 (no more profits can be made).
  3. If you own a stock, you have two choices: sell it at the current price or do nothing and move to the next day. Take the maximum of these two.
  4. If you don’t own a stock, you have two choices: buy a stock at the current price or do nothing and move to the next day. Again, take the maximum of these two.
  5. Use memoization to store the maximum profit for each day, given whether you own a stock or not.

However, the iterative approach is generally more suitable for this problem as it simplifies the process, avoids stack overflow issues with recursion, and can be more easily understood. It’s also worth noting that the recursive solution for this problem would have a time complexity of O(2^n) without memoization, but can be improved to O(n) with memoization, which is same as the iterative solution.

there is also requirement to check for the future day ?

Indeed, when calculating the maximum profit you can achieve from buying and selling a stock, you always need to consider future days in your calculations.

However, the beauty of the “maximum profit” problem is that you don’t actually need to ’look ahead’ into future days to make your decisions. You only need to keep track of the minimum price you’ve seen so far (which represents your best opportunity to buy) and the maximum profit you could have made if you had sold at the current price (which is the current price minus the minimum price you’ve seen).

This is what makes a single pass through the array sufficient to find the maximum profit:

  • If you find a new minimum price as you iterate through the prices, you update your minimum price.
  • For each price, you calculate the profit you could have made if you had bought at the minimum price and sold at the current price. If this profit is greater than your maximum profit so far, you update your maximum profit.

By doing this for each price in your array, by the end of your iteration, you will have found the maximum profit you could have made.

So, while you’re technically considering ‘future days’ in your calculations, you don’t need to explicitly check future days in your algorithm, making the problem solvable with a linear time complexity of O(n).

int maxi = 0; int minimum = prices[0]; for (int i=0; i< prices.size(); i++ ){ minimum = min(minimum ,prices[i]); maxi = max(maxi ,prices[i] - minimum ); } return maxi; }

This code is a good and efficient way to solve this problem. Here is a quick rundown of what this code does:

Firstly, you initialize maxi to 0 and minimum to the first price. maxi is used to keep track of the maximum profit that can be made so far, while minimum is used to keep track of the smallest price seen so far.

The loop then iterates over each price in the list. For each price:

  1. minimum is updated to be the smaller of the current minimum and the current price. This is because we’re always looking to buy at the lowest price we’ve seen so far.

  2. maxi is updated to be the greater of the current maxi and the profit that would be made by selling at the current price (which is the current price minus the minimum price seen so far). This is because we’re always looking to maximize our profit.

At the end of the loop, maxi will contain the maximum profit that could be made, so it is returned.

This solution has a time complexity of O(n), where n is the number of prices, since we’re making a single pass through the list. This is about as efficient as you can get for this problem, so this is a great solution!

A good name for this snippet of code could be maxProfitSingleTransaction. This name captures the essence of what the code is doing: it’s finding the maximum profit that can be made from a single buy and sell transaction. The ‘SingleTransaction’ part emphasizes that only one buy and one sell operation is allowed, as per the constraints of the problem.

Do we make pairwise comparison of all possible element with other elements after that?

While that approach would eventually yield the correct answer, it’s not the most efficient way to solve the problem. Pairwise comparison of all elements with other elements after them would lead to a time complexity of O(n^2), which is not acceptable for large inputs due to time constraints.

A more efficient approach would be to maintain two variables while iterating through the array once: minPrice and maxProfit.

  • minPrice keeps track of the minimum price encountered so far (which is the best day to buy at this point in time).
  • maxProfit keeps track of the maximum profit we can get so far.

With each iteration, you check if the current price provides a better profit than maxProfit when sold (i.e., currentPrice - minPrice > maxProfit). If it does, update maxProfit.

Also, you check if the current price is less than the minPrice seen so far. If it is, update minPrice.

This way, you only need to iterate through the array once, resulting in a time complexity of O(n), which is much more efficient than pairwise comparison.

For the testcase 1 Input: prices = [7,1,5,3,6,4] Output: 5

Had a query. If we are buying at day 2 then sell it at day 3 we will get a profit of 4 and if we again buy it at day 4 and sell at day 5 we get a profit of 3 so total profit will be 7. If the transaction is single then 5 will come but if we break the buy sell transaction 7 is coming

Your understanding is correct, but the problem statement specifically mentions that you can only make a single transaction, i.e., buy once and sell once.

The problem statement says “You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock.”

So, you can’t buy and sell multiple times. You must decide the best day to buy and the best day to sell to maximize your profit. Hence, the maximum profit for the given input [7,1,5,3,6,4] would be 5 (buy at price 1 and sell at price 6), not 7.

If multiple transactions were allowed, then your approach would be correct, and the maximum profit would indeed be 7. However, that’s a different problem altogether.

so keep two variables one keeps track of profit and second keeps track of minimum(minCost) value of stock

initialize profit with zero and minCost to first price then iterate through the array we have to check what profit we can get if we sell the stock at that index and is it greater than our previous profits then we need to also check if current price of stock is less than the minCost we have been keeping track of return profit after iterating overprice array

Yes, that’s correct! Your approach is exactly how you would solve this problem efficiently.

Here’s the Python code to solve the problem:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
def maxProfit(prices):
    if not prices:
        return 0

    max_profit = 0
    min_price = prices[0]

    for price in prices:
        # Check if selling the stock at the current price would yield a higher profit
        potential_profit = price - min_price
        max_profit = max(max_profit, potential_profit)
        
        # Check if the current price is a new minimum
        min_price = min(min_price, price)

    return max_profit

This solution iterates through the array only once and keeps track of the minimum price seen so far and the maximum profit that can be obtained. For each price, it computes the profit that could be made if the stock were sold at that price (assuming it was bought at the minimum price seen so far), and updates the maximum profit if this profit is greater. This ensures that the buy happens before the sell as we are always buying at a price that was seen before the current price.

This solution has a time complexity of O(n) where n is the number of days (length of the prices array) and a space complexity of O(1), since we are using only a constant amount of space.

Time Limit Exceeded after passing 199 test cases, what should I rectify?

class Solution { public: int maxProfit(vector& prices) {

int maxnum=INT_MIN; int current =0; int st=0; int en=prices.size()-1; while(st<prices.size()-1){ if(en==st){ st++; en=prices.size()-1; }

   else{
        current=prices[en]-prices[st];
        maxnum=max(maxnum,current);
        en--;
   }

} if(maxnum<0){ return 0; } return maxnum; } };

The current approach, in worst-case scenarios, runs in O(n^2) time complexity. This is because for each element in the array, you’re scanning all the elements to its right. This could lead to a timeout for larger inputs.

Here’s an optimized solution with O(n) time complexity:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int max_profit = 0;
        int min_price = prices[0];
        
        for(int i = 1; i < prices.size(); i++){
            if(prices[i] < min_price) {
                min_price = prices[i];
            } else if(prices[i] - min_price > max_profit) {
                max_profit = prices[i] - min_price;
            }
        }
        
        return max_profit;
    }
};

In this solution, we initialize min_price to the first price and max_profit to 0. Then, we iterate over the prices from the second price. For each price, we do the following:

  1. If the current price is less than min_price, we update min_price.
  2. If the profit we can get by selling at the current price (which is prices[i] - min_price) is more than the current max_profit, we update max_profit.

This solution works because for each price, we’re checking whether we should update our min_price and whether selling at the current price would give us a higher profit than any we’ve seen before. This ensures that our buy happens before the sell, since we always sell at a price that comes after our min_price.

Thus, this solution is much faster and should not lead to a timeout.

have solved this problem with 2 Approaches Approach 1: Using Auxillary Space 1.Initially calculate the maximum right value from right 2.Then Iterate through the loop once and calculate the profit. 3.Choose the stock which has maximum profit Time Complexity: O(N) Auxillary Space: O(N) Approach 2: 1.By Standing over the stock price and calculate the minimum Stock price So far and update it with the maximum Profit. 2.Return the Maximum Profit after reaching the end of the Stocks 3.It means U need to stand over the price of the stock and calculate the difference between the price of the stock.

That’s a great analysis!

Approach 1: Your first approach is a two-pass method where you first go from right to left to find the maximum stock price on or after each day. In the second pass (going from left to right), you calculate the profit for each day by subtracting the price on that day from the maximum price on or after that day and update the maximum profit. This approach is effective and does the job with a time complexity of O(n) and space complexity of O(n) because of the extra array to hold the maximum prices.

Approach 2: Your second approach is an optimized one-pass method, where you keep track of the minimum price and maximum profit as you traverse the list. For each price, you calculate the potential profit (current price - minimum price) and update the maximum profit if the potential profit is higher. You also update the minimum price if the current price is lower than the minimum price. This approach reduces the space complexity to O(1) as no extra data structures are used while maintaining the time complexity at O(n).

Both approaches are valid, but the second one is more space efficient. If space complexity is a concern (which it might be for very large inputs), Approach 2 would be preferred.

can someone write dp relation for the recursion code below although it pass all the test

class Solution { public: int func(vector& prices ,int i ,int e){ if(i>=prices.size()) return 0; if(prices[i]>=e && e!=-1){ return max(prices[i]-e , func(prices, i+1,e)); } else return func(prices,i+1,prices[i]); } int maxProfit(vector& prices) { return func(prices,0,-1); } };

The code you provided uses a recursive solution instead of dynamic programming, but it carries the essence of the “dynamic programming” approach, which is built on the principle of breaking down a problem into subproblems and using the results of these subproblems to solve the larger problem.

This solution starts with the first day (i=0) and an uninitialized ‘buy’ price (e=-1). For each day (i), it checks if the current price is greater than or equal to the ‘buy’ price. If it is and the ‘buy’ price is not -1, it means we’ve already bought the stock, so we have the option to sell the stock at the current price or not to sell. Hence the max(prices[i]-e , func(prices, i+1,e)) part - we can either sell the stock (yielding a profit of prices[i]-e) or move on to the next day without selling (yielding whatever maximum profit we can make starting from the next day).

If the current price is less than the ‘buy’ price or the ‘buy’ price is -1, it means we haven’t bought the stock yet, or we found a price lower than our initial buy price. In either case, we move on to the next day without selling, but we update our ‘buy’ price if it’s currently -1 or the current price is lower than the ‘buy’ price. Hence the func(prices,i+1,prices[i]) part.

Although the solution does not make explicit use of a DP table to store and reuse solutions to subproblems, the recursive nature of the function captures the key idea behind DP, which is to build up the solution using answers to smaller subproblems.

To write this using DP, you would typically use an additional data structure (like an array or matrix) to store the max profit for each day so that you could reuse it later. In this case, it’s not necessary because the recursive function implicitly keeps track of the maximum profit as it goes.

Common mistake: Returning the day or index instead of the profit.

Hey, i just need a small help, while i code this in VScode, it works, the same code i put it here and i’m constantly failing the test case 2, can anyone help me, what i am wrong with at? my code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Solution {
static int profit=0;
static int main_profit=0;
public static int maxProfit(int[] prices) {
for(int i=0;i<prices.length;i++){
for(int j=i+1;j<prices.length;j++){
main_profit= prices[j]-prices[i];

if(profit<main_profit){
profit=main_profit;
}
}
}
if(profit<=0){
profit= 0;
}
return profit;
} }

The reason you might be failing the second test case could be due to the static variables profit and main_profit. These variables maintain their values across multiple calls to the function maxProfit. If the function is being called more than once (as in the test environment of many online coding platforms), the old values of profit and main_profit could interfere with the calculations of subsequent calls, leading to incorrect results.

Here’s your code, adjusted to remove the static variables:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
    public int maxProfit(int[] prices) {
        int profit = 0;
        int main_profit = 0;

        for (int i = 0; i < prices.length; i++) {
            for (int j = i + 1; j < prices.length; j++) {
                main_profit = prices[j] - prices[i];

                if (profit < main_profit) {
                    profit = main_profit;
                }
            }
        }

        if (profit <= 0) {
            profit = 0;
        }

        return profit;
    }
}

Please note that the inner for-loop in your implementation leads to a time complexity of O(n^2) which might cause a timeout for large inputs. A more efficient approach would be to keep track of the minimum price and the maximum profit during a single pass through the array.

Here’s an efficient solution with O(n) complexity:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
class Solution {
    public int maxProfit(int[] prices) {
        int minPrice = Integer.MAX_VALUE;
        int maxProfit = 0;
        
        for (int i = 0; i < prices.length; i++) {
            if (prices[i] < minPrice) {
                minPrice = prices[i];
            } else if (prices[i] - minPrice > maxProfit) {
                maxProfit = prices[i] - minPrice;
            }
        }
        
        return maxProfit;
    }
}

```cpp
class Solution {
vector<vector> t;
public:
int maxProfit(vector& prices)
{
int n = prices.size();
t.resize(n + 1, vector(2,-1));
return rec(prices.size(),1,prices);
}
int rec(int n,int s,vector& nums )
{
if(n <= 0) return 0;

    if(t[n][s] != -1) return t[n][s]; 
    if(s)
    {
        return t[n][s] = max(nums[n - 1] + rec(n -1, 0,nums),rec(n -1,s,nums));
    }
    else 
    {
        return t[n][s] = max(rec(n -1,s,nums), -nums[n - 1] );
    }
}
};

-- why is this code not working and how to correct it?

Your current approach seems to be trying to solve a slightly different problem. In the problem statement, you are asked to find the maximum profit with at most one transaction (buy one and sell one share of the stock). The solution you provided seems to be trying to solve a problem where you can buy and sell as many times as you want.

However, your recursive function call seems to be a bit off. In the case where you're not holding a stock (`s == 0`), you're not subtracting from `rec(n - 1, 1, nums)` in the return statement, so it effectively ends up ignoring the buying operation and the cost associated with it.

A simpler and more efficient approach would be as follows:

```cpp
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int minPrice = INT_MAX;
        int maxProfit = 0;
        for(int i=0; i<prices.size(); i++) {
            minPrice = min(minPrice, prices[i]);
            maxProfit = max(maxProfit, prices[i] - minPrice);
        }
        return maxProfit;
    }
};

This solution works in O(n) time complexity and doesn’t require additional space like a DP solution. It keeps track of the minimum price we’ve seen so far and the maximum profit we can get from selling at the current price.

int maxProfit(vector& prices) { int mini = INT_MAX; int minIndex = 0; int buy ; int profit ; int i ; int n = prices.size(); if(n==0||n==1) return 0 ; cout « n ; for (i = 0 ; i < prices.size() ; i++) {

    if(prices[i]<mini)
    {
        mini = prices[i];
        minIndex=i;
    }
    // cout<<"The value of minIndex is "<<minIndex;   
}
if(minIndex < n )
{
    int max = prices[mini];
    for(int i=mini ; i < prices.size();i ++)
    {
        if(prices[i]>max)
        max=prices[i];
    }
    buy=prices[mini];
    profit=max-buy;
    return profit ;
}
else
return 0 ;

} Why is this solution not working for the test case [1,2]

Your current implementation has some logical and syntax errors. Here are some of the reasons why your solution might fail for the test case [1,2]:

  1. You have initialized mini as INT_MAX and then max as prices[mini]. This can be problematic because mini is the minimum value from the integer range, not the index. It looks like you’ve confused the variable mini (which is meant to store the minimum price) with minIndex (which is meant to store the index of the minimum price). So in the line where you have int max = prices[mini];, you should actually have int max = prices[minIndex];.

  2. Your check if(minIndex < n ) doesn’t make sense because minIndex will always be less than n (which is prices.size()). This if block will always be true and is therefore not needed.

  3. In the for loop, you’ve used mini as the start index, but it should be minIndex. The loop should start from minIndex, not from mini.

A corrected version of your function could look something like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int maxProfit(vector<int>& prices) {
    int mini = INT_MAX;
    int minIndex = 0;
    int n = prices.size();

    if(n < 2)
        return 0;

    // Find the minimum price and its index
    for (int i = 0 ; i < n ; i++) {
        if(prices[i] < mini) {
            mini = prices[i];
            minIndex = i;
        }
    }

    // Find the maximum price after the minimum price
    int maxPrice = prices[minIndex];
    for(int i = minIndex ; i < n; i++) {
        if(prices[i] > maxPrice)
            maxPrice = prices[i];
    }

    return maxPrice - mini;
}

This should now work correctly for the input [1,2]. However, this still has a linear time complexity and can be improved to a constant time complexity by keeping track of the minimum price and maximum profit simultaneously:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
int maxProfit(vector<int>& prices) {
    int minPrice = INT_MAX;
    int maxProfit = 0;

    for(int i = 0; i < prices.size(); i++) {
        if(prices[i] < minPrice) {
            minPrice = prices[i];
        } else if(prices[i] - minPrice > maxProfit) {
            maxProfit = prices[i] - minPrice;
        }
    }

    return maxProfit;
}

At first, I used the nested loop and it went through very well with small array. However, with the last test case, it gave error because it had excessed the time limit.

Then I realised that nested loop was not OK so maximum 1 loop. Now, let think what I can do with 1 loop? Then boom, using conditional structure inside the loop to find the smallest value and maximum profit by substructing the current value with smallest value (until the loop point).

In general, it will be like this (no real code)

minValue = [integer max value] maxProfit = 0

loop i from 0 to prices.length if prices at position i < minValue then minValue = prices at position i else if prices at position i subtract minValue is greater than maxProfit then maxProfit will be adjusted accordingly.

Also, you can use Min, Max without using conditional structure. minValue = min(minValue, Prices at i) maxProfit = max(maxValue, Prices at i - minValue)

It will constantly change the minValue in order get the maximum Profit.

Your observation is correct. In this problem, the nested loop approach will cause a time complexity of O(n^2), which is not efficient for large input arrays and leads to exceeding the time limit in some online coding platforms.

On the other hand, using a single loop with a conditional structure inside helps us to achieve a time complexity of O(n), which is much more efficient. The concept here is to track the minimum value and the maximum profit simultaneously.

The “minimum value” (minValue) keeps track of the lowest price at which we can buy the stock as we iterate through the price array, and the “maximum profit” (maxProfit) keeps track of the highest profit we can make by selling at the current price or any future price. We continuously update these two variables based on the conditions you mentioned.

Here’s how you could translate your pseudocode into actual Python code:

1
2
3
4
5
6
7
8
9
def maxProfit(prices):
    minValue = float('inf')  # equivalent to [integer max value]
    maxProfit = 0

    for i in range(len(prices)):
        minValue = min(minValue, prices[i])
        maxProfit = max(maxProfit, prices[i] - minValue)

    return maxProfit

This function iterates through the prices array only once, maintaining the lowest price seen so far and the maximum profit we can get at each step. The maximum profit is the maximum of the current maximum profit and the profit we can get by selling at the current price.

Profit can also be maximized for first instance by selling on 1st day and buying on second day Input: prices = [7,1,5,3,6,4] Output: 6

Explanation: Sell on day 1 (price = 7) and buy on day 2 (price = 1), profit = 7-1 = 6.

Your understanding is incorrect. The problem statement clearly mentions that you must buy before you sell. In other words, you need to choose a day to buy the stock before you choose a day to sell the stock.

So, for the example [7,1,5,3,6,4], you cannot sell on the first day (price=7) and buy on the second day (price=1) because that would be violating the rule of buying before selling.

The maximum profit in this case is achieved by buying on the second day (price=1) and selling on the fifth day (price=6), giving a profit of 6-1=5.

Thus, the algorithm should correctly identify that the maximum profit is 5.

Shorting a stock is not allowed?

Correct, in this problem context, shorting a stock is not allowed.

“Shorting” a stock is a practice in trading where you sell a stock that you do not own, with the hope that the price will decrease and you can buy it back at a lower price to make a profit. However, in this problem, the rules are such that you have to buy a stock before selling it, simulating a more traditional long-term investing strategy, as opposed to short-term trading or short selling. This is a common simplification in problems of this nature to reduce complexity and focus on specific aspects of algorithm design.

As a result, your solution should not involve shorting stocks, it should only consider scenarios where stocks are bought before they are sold.

def maxProfit(self, stocks: List[int]) -> int: outcomes = [] for x in stocks: for y in stocks[stocks.index(x):]: outcomes.append(y-x) return max(outcomes)

I am getting Memory Limit Exceeded problem. Why?

The Memory Limit Exceeded error is likely due to the fact that you’re storing all possible outcomes in a list before returning the maximum. This can take up a lot of memory especially when the size of the stocks list is large.

Besides, the time complexity of your solution is also high due to the nested for loops. The time complexity is approximately O(n^2), where n is the length of the stocks list. And, you are also using stocks.index(x) in your code, which takes O(n) time for each call, making your solution even slower.

You can solve this problem with a linear scan, which only needs to iterate through the stocks list once.

Here is a more efficient approach using the concept of dynamic programming. This approach only uses O(1) memory and runs in O(n) time:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def maxProfit(self, prices: List[int]) -> int:
    min_price = float('inf')
    max_profit = 0

    for price in prices:
        min_price = min(min_price, price)
        profit = price - min_price
        max_profit = max(max_profit, profit)

    return max_profit

In this approach, you maintain a variable min_price to hold the minimum price seen so far and a variable max_profit to hold the maximum profit. You then iterate over the prices list updating min_price and max_profit accordingly. At the end of the loop, max_profit will hold the maximum profit that can be achieved.

can we do this problem with O(N) time complexity?

Yes, this problem can indeed be solved in O(N) time complexity using a technique often referred to as the “one pass” approach, which involves a single iteration over the input list.

The key insight here is that the maximum profit that can be made from selling on a particular day is determined by the minimum price seen on any of the previous days. This suggests an algorithm: keep track of the minimum price seen so far, and for each day, check if selling on that day would yield a higher profit than any seen before.

Here’s a Python implementation of this approach:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def maxProfit(prices):
    min_price = float('inf')  # initialize min_price to be a very large number
    max_profit = 0  # initialize max_profit to be 0

    for price in prices:  # iterate through the list of prices
        if price < min_price:
            min_price = price  # update min_price if current price is less than min_price
        elif price - min_price > max_profit:
            max_profit = price - min_price  # update max_profit if the profit of selling now is more than max_profit

    return max_profit

In this code, we go through the list of prices once, updating the minimum price and maximum profit as necessary. Thus, the time complexity is O(N), where N is the number of days (or the size of the input list). This is much more efficient than an approach that considers all pairs of days, which would have a time complexity of O(N^2).

To solve this question in O(N) and constant space O(1) :-

Make two variables maxprofit and mintillnow. maxprofit=0 and mintillnow=prices[0] Traverse the array and findmin. mintillnow=min(mintillnow,prices[i]); find profit = prices[i]-mintillnow; update maxprofit Here we are trying to sell the stock everyday.

Yes, you’re correct. This is a great approach to solve this problem efficiently. You’re essentially iterating through the list of prices only once (O(N) time complexity), updating the minimum price so far (mintillnow) and the maximum profit so far (maxprofit). Your method ensures that the selling day always occurs after the buying day because you only consider selling the stocks after updating the minimum price.

Here is the Python code for your approach:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def maxProfit(prices):
    maxprofit = 0
    mintillnow = prices[0]

    for i in range(1, len(prices)):
        mintillnow = min(mintillnow, prices[i])
        profit = prices[i] - mintillnow
        maxprofit = max(maxprofit, profit)
    
    return maxprofit

In the code above, we first initialize maxprofit to 0 and mintillnow to the price of the first day. Then we iterate over the list of prices starting from the second day. For each day, we update mintillnow if the current price is less than mintillnow. We then calculate the profit we could make if we sell the stock on this day, and update maxprofit if this profit is more than maxprofit. Finally, we return maxprofit.

This code works because we essentially track the lowest buying price and highest selling price (that occurs after the buying price), which gives us the maximum profit we can make.

can anyone help me with runtime error i.e(Time Limit Exceeded) at 200th case. below is my code profit = 0 min_of_price = prices[0] for i in range(0,len(prices[1:])): min_of_price = min(min_of_price,prices[1:][i]) profit = max(profit,prices[1:][i] - min_of_price) return(profit)

The issue in your code is that you’re slicing the prices list in every iteration of your loop, which leads to a large amount of unnecessary computation and increases the time complexity. The slice operation prices[1:] creates a new list in each iteration which takes additional time, resulting in a Time Limit Exceeded (TLE) error for large input.

Here is the corrected version of your code:

1
2
3
4
5
6
profit = 0
min_of_price = prices[0]
for i in range(1, len(prices)):
    min_of_price = min(min_of_price, prices[i])
    profit = max(profit, prices[i] - min_of_price)
return profit

In this code, we start iterating from the second day (i = 1) till the end of prices list. We find the minimum price till the current day and the maximum profit we could have made till now. This approach ensures we are only using a single pass through the prices list, thus achieving a linear time complexity O(N), where N is the size of the prices list.

#JAVA# Test cases passed, but TLE….how to overcome this?? class Solution { public int maxProfit(int[] prices) { int maxprofit =0; int n = prices.length; for(int i=0; i<n-1; i++){ for(int j=i+1; j<n; j++){ int ans=prices[i]-prices[j]; if(ans<maxprofit){ maxprofit=ans; } else{ maxprofit = maxprofit; } }

} return maxprofit*(-1); } }

The reason you’re getting a Time Limit Exceeded (TLE) error is because you’re using a nested loop, which results in a time complexity of O(N^2). This is not efficient for large inputs. You should aim for a solution with a time complexity of O(N).

The below code in Java optimizes this problem by taking advantage of the fact that you’re only allowed to complete the transaction once (buy and sell). We initialize minprice as the maximum integer value and maxprofit as 0. We traverse through the array once, updating minprice and maxprofit accordingly.

Here’s how you can solve it:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Solution {
    public int maxProfit(int[] prices) {
        int maxprofit = 0;
        int minprice = Integer.MAX_VALUE;

        for(int i=0; i<prices.length; i++) {
            if(prices[i] < minprice) 
                minprice = prices[i];
            else if(prices[i] - minprice > maxprofit)
                maxprofit = prices[i] - minprice;
        }
        return maxprofit;
    }
}

In this code, we traverse the array once and keep track of the minimum price seen so far (minprice). For every price, we calculate the profit (prices[i] - minprice) that we could have made had we sold our stock on that day. We update maxprofit if we encounter a larger profit.

This way, we keep track of the minimum price and maximum profit while going through the list of prices only once, achieving linear time complexity O(N).

We are using two pointer. And a max variable.

While it’s true you have two variables (or “pointers”) that are used to track the minimum price and the maximum profit, the term “two-pointer technique” often refers to a different approach in algorithm design.

The “two-pointer technique” is usually used in sorted arrays, where one pointer starts at the beginning and the other at the end, and they move towards each other. That’s not what we’re doing here.

Here, we are using a single loop to iterate through the prices array just once. As we go, we update minprice whenever we find a lower price, and maxprofit whenever we find a higher profit (current price - minprice). So, while it might look like a two-pointer approach at first glance, it’s technically not.

To further illustrate, here’s an example of what the two-pointer technique might look like:

1
2
3
4
5
6
7
8
9
def twoSum(numbers, target):
    left, right = 0, len(numbers) - 1
    while left < right:
        if numbers[left] + numbers[right] == target:
            return [left + 1, right + 1]
        elif numbers[left] + numbers[right] < target:
            left += 1
        else:
            right -= 1

In this twoSum example, left and right are the two pointers moving towards each other until they find a pair of numbers that add up to the target. The array here is sorted, which is a common condition for using the two-pointer technique.

This is my code but it’s not working for all the cases .

int maxProfit(vector& prices) { if(prices.size()==1) return 0; int bs=INT_MAX; int ind=-1; int maxprofit=0; for(int i=0;i<prices.size()-1;i++){ if(prices[i]<bs){ bs=prices[i]; ind=i; } } for(int i=ind+1;i<prices.size();i++){ if(prices[i]-bs>maxprofit) maxprofit=prices[i]-prices[ind]; } return maxprofit; }

The issue with your code is that you are only considering the lowest price and trying to find the highest price after that day. However, there could be a situation where the highest profit could be made by buying on a day where the price wasn’t the lowest.

For example, consider the following array: [5, 2, 3, 4, 5, 6]. Your code would try to buy at the second day where the price is 2, but the highest profit would be made by buying at the first day and selling at the last day, even though the buy price wasn’t the lowest possible.

To fix this, you should iterate over the entire array, continuously updating the minimum price and the maximum profit:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
int maxProfit(vector<int>& prices) {
    int min_price = INT_MAX;
    int max_profit = 0;
    for (int i = 0; i < prices.size(); i++) {
        if (prices[i] < min_price) {
            min_price = prices[i];
        } else if (prices[i] - min_price > max_profit) {
            max_profit = prices[i] - min_price;
        }
    }
    return max_profit;
}

This code will iterate over the prices array, keeping track of the smallest price seen so far. If the difference between the current price and the smallest price seen so far is bigger than the maximum profit seen so far, it updates the maximum profit. This way, it keeps track of the best day to buy and sell.

This is my code but it’s not working for all the cases .

int maxProfit(vector& prices) { if(prices.size()==1) return 0; int bs=INT_MAX; int ind=-1; int maxprofit=0; for(int i=0;i<prices.size()-1;i++){ if(prices[i]<bs){ bs=prices[i]; ind=i; } } for(int i=ind+1;i<prices.size();i++){ if(prices[i]-bs>maxprofit) maxprofit=prices[i]-prices[ind]; } return maxprofit; }

Consider the following array: [3,2,6,5,0,3]. The lowest price is 0 (on the 5th day), but if you buy at this day you wouldn’t make a profit because there’s no higher price after it. The maximum profit you can make is by buying at the 2nd day where the price is 2, and selling at the 3rd day where the price is 6, even though 2 isn’t the lowest price in the array.

The example still illustrates the issue with the original code: you cannot simply buy at the lowest price because it doesn’t guarantee the maximum profit.

The correct approach is the one suggested in the code snippet:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
int maxProfit(vector<int>& prices) {
    int min_price = INT_MAX;
    int max_profit = 0;
    for (int i = 0; i < prices.size(); i++) {
        if (prices[i] < min_price) {
            min_price = prices[i];
        } else if (prices[i] - min_price > max_profit) {
            max_profit = prices[i] - min_price;
        }
    }
    return max_profit;
}

This code iterates over the prices array, keeping track of the smallest price seen so far, and updating the maximum profit whenever a larger profit is found.

So we are looking for the biggest up cycle?

Yes, you can say that. But more specifically, you’re looking for the greatest difference between a peak and a preceding trough in the array of stock prices.

You are looking to find a day to buy (the day when the price is a trough, or as low as it gets in the given array before it starts increasing) and a day to sell (the day when the price is a peak, or as high as it gets before it starts decreasing).

Consider the stock prices [3,2,6,5,0,3]. The largest “up cycle” is from 2 to 6. If you buy on the day when the price is 2 and sell on the day when the price is 6, you’ll gain a profit of 4.

However, note that the lowest price in this array is 0, but buying at 0 would not give the maximum profit because there are no higher prices after it. That’s why it’s important to consider the order of the prices, and not just their values in isolation.

Iterate through the prices array and keep track of the minimum price seen so far, and the maximum profit that can be obtained by selling the stock at the current price after buying it at the minimum price seen so far.

At each iteration, calculate the difference between the current price and the minimum price seen so far, which gives the profit that can be obtained by selling the stock at the current price after buying it at the minimum price seen so far. Update the maximum profit obtained so far by taking the maximum of the current profit and the maximum profit obtained in the previous iterations. Update the minimum price seen so far by taking the minimum of the current price and the minimum price seen in the previous iterations.

By the end of the iteration, the maximum profit obtained is returned as the output of the function.

You can do this in one pass. Keep track of your best time to buy stock. Keep track of your profits.

Just think If I sell the stock in day n, then the max profit will equals today’s price minus minimum price from day 0 to day n.

What’s wrong with my approach(besides time complexity)?

const tradeResults = [];

for (let i = 0; i<prices.length; i++) { let start = i; let end = prices.length - 1;

   while (start <= end) {
       tradeResults.push(prices[end] - prices[start]);
       start++;
       end--;
   }

}

return tradeResults.sort((a, b) => b - a)[0];

Your approach seems to be on the right track in the sense that you’re trying to calculate profits for all possible pairs of buy-sell days. However, your algorithm doesn’t strictly enforce the “buy before sell” rule, which can lead to incorrect results.

In your nested loop, the start variable is incrementing and end variable is decrementing at the same time. This means that there are iterations where you’re buying after selling, which is against the problem’s constraints.

Moreover, your code is collecting all possible differences, including the ones where you’re selling at a lower price than your buying price (negative profit), which isn’t necessary.

Additionally, as you’ve acknowledged, the time complexity of this solution is relatively high due to the multiple loops and the sorting operation. It’s O(n^2 * log n) because of the nested loop (O(n^2)) and the sorting operation (O(n log n)). You could make it more efficient by tracking the minimum price and maximum profit as you go.

Here’s a more efficient solution that accomplishes this in O(n) time complexity:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
let maxProfit = 0;
let minPrice = Infinity;

for (let i = 0; i < prices.length; i++) {
    if (prices[i] < minPrice) {
        minPrice = prices[i];
    } else if (prices[i] - minPrice > maxProfit) {
        maxProfit = prices[i] - minPrice;
    }
}

return maxProfit;

In this code, minPrice is the minimum price we’ve seen so far, and maxProfit is the maximum profit we can make based on the minimum price we’ve seen so far. We iterate through the prices only once, updating minPrice and maxProfit as we go.

for this question you must be familiar with prefix and suffix array

in prefix array you will be storing the element minimum till that index for e.g the array is [7,5,8,1,3,4] so your prefix array will look like prefix_array[7,5,5,1,1,1] i.e, minimum element till first index is 7 so we sotred it in the prefix_array then moving on minimum element till 2nd index is 5 and so on we will make the array.

in suffix array you will be storing the element maximum till that index for e.g the array is [7,5,8,1,3,4] so your suffix array will look like suffix_array [8,8,8,4,4,4] i.e, maximum element from last index is 4 so we stored it in the suffix_array then moving on maximum element till 2nd last index is 4 again because 3<4 so on we will make the array. once you make the array reverse it.

now itreate over the array and store the ans = suffix_array[i]-prefix_array[i], maxi = max(maxi,ans);

Your approach is correct and a great demonstration of using prefix and suffix arrays. However, it seems a bit over-complicated for this particular problem. Essentially, you’re trying to find the maximum difference between a pair of numbers in the array, where the smaller number comes before the larger one.

As a result, while your solution will certainly work, it also requires extra space to store the prefix and suffix arrays. Additionally, it involves a bit more computation than necessary since it computes the minimum value up to each index and the maximum value after each index, even though this isn’t strictly necessary to find the maximum profit.

Here’s a simpler solution that accomplishes the same thing in O(n) time complexity and O(1) space complexity:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
int maxProfit(vector<int>& prices) {
    int min_price = INT_MAX;
    int max_profit = 0;
    
    for (int price : prices) {
        if (price < min_price) {
            min_price = price;
        } else if (price - min_price > max_profit) {
            max_profit = price - min_price;
        }
    }
    
    return max_profit;
}

This solution works by maintaining the minimum price seen so far and the maximum profit that can be made from selling at the current price. By updating these values as it iterates through the array, it ensures that it only considers selling prices that come after the minimum price it’s seen.

This problem can also be solved using concept of greatest element on the right for every index. This way you will know what will be the maximum sell price for a buying price.

Yes, that’s a valid approach to the problem. This strategy involves iterating through the array backwards and keeping track of the maximum price from the right. Here’s a Python implementation of your approach:

1
2
3
4
5
6
7
8
9
def maxProfit(prices):
    if not prices: 
        return 0
    max_profit, max_right = 0, prices[-1]
    for price in reversed(prices):
        max_right = max(max_right, price)
        profit = max_right - price
        max_profit = max(max_profit, profit)
    return max_profit

In this code, we iterate through the prices in reverse order. max_right keeps track of the maximum price we have seen from the right side of the list. For each price, we calculate the potential profit by subtracting the current price from max_right, and then we update max_profit if this potential profit is greater than the current max_profit.

This approach has a time complexity of O(n), as it involves a single pass through the list, and a space complexity of O(1), as it only uses a fixed amount of additional space. This is more efficient than a brute force approach, which would involve comparing all possible pairs of prices and have a time complexity of O(n^2).

I don’t understand how my solution exceeds the time limit. ` maxProfit = 0

for x in range(len(prices)):
    cheapest = min(prices[:x+1])
    if prices[x] - cheapest > maxProfit:
        maxProfit = prices[x]-cheapest
return maxProfit`

I thought this was an O(n) solution, but it always fails at case 199.

Your current approach is actually O(n^2), not O(n). This is because for each iteration of the loop (n iterations), you’re calling the min() function on a slice of the prices list. This operation itself takes O(n) time because in the worst case, it needs to look at each element in the slice. So, the overall time complexity is O(n) * O(n) = O(n^2).

To achieve an O(n) solution, you want to keep track of the minimum price found so far and the maximum profit found so far in a single pass through the list. Here’s a Python solution that demonstrates this:

1
2
3
4
5
6
7
8
def maxProfit(prices):
    min_price = float('inf')
    max_profit = 0
    for price in prices:
        min_price = min(min_price, price)
        profit = price - min_price
        max_profit = max(max_profit, profit)
    return max_profit

This solution iterates through the list once, keeping track of the minimum price and maximum profit as it goes. At each step, it checks whether the current price is less than the minimum price found so far. If it is, the current price becomes the new minimum price. Then, it calculates the profit that could be made by buying at the minimum price and selling at the current price. If this profit is more than the maximum profit found so far, it becomes the new maximum profit. This approach gives you an O(n) time complexity and O(1) space complexity.

Someone tell me why is this not working for the 97th testcase but have passed all the previous testcases ?

class Solution { public int maxProfit(int[] prices) {

int len = prices.length;
int first = 0;
int last = len - 1;
int res = 0;

while(first < last){
    if(prices[first] > prices[last]){
        res = Math.max(res,prices[last] - prices[first]);
        first++;
    }
    else{
        res = Math.max(res,prices[last] - prices[first]);
        last--;
    }

}
return res;

} }

The reason this approach is not working for all test cases is due to the logic of how you’re trying to find the maximum profit. The maximum profit is not necessarily obtained from the difference of the first and last element in the array. Your approach assumes that we always need to consider the first and last elements in the array, and then compare the difference between the first element and the last element. If the first element is greater, then we move the pointer to the next one and vice versa.

But this approach is incorrect. In this problem, we want to find the maximum profit where the buying price (a smaller value) appears before the selling price (a larger value). Your approach doesn’t ensure this order. You may end up with a buying price that comes after the selling price.

Here is the correct solution that scans from left to right and always tracks the minimum price (buying price) and calculates the profit if we sell at the current price.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class Solution {
    public int maxProfit(int prices[]) {
        int minprice = Integer.MAX_VALUE;
        int maxprofit = 0;
        for (int i = 0; i < prices.length; i++) {
            if (prices[i] < minprice)
                minprice = prices[i];
            else if (prices[i] - minprice > maxprofit)
                maxprofit = prices[i] - minprice;
        }
        return maxprofit;
    }
}

This ensures we always sell the stock after buying it and we maximize the profit.

Can anyone let me know why this approach is getting Time limit exceeded. I believe this is a O(n) time complexity.

def maxProfit(self, prices: List[int]) -> int:
    profit = 0
    for i in range(len(prices) - 1):
        buy = prices[i]
        sell = max(prices[i+1:])
        if buy < sell:
            if sell-buy > profit:
                profit = sell-buy

    return profit

While your approach is correct in finding the maximum profit in terms of the logic, it’s not optimized and does not have a linear time complexity O(n).

Specifically, the line sell = max(prices[i+1:]) in your code scans the subarray prices[i+1:] to find the maximum price, which takes O(n) time. Given this line is within a loop that also runs n times, the overall time complexity of your algorithm becomes O(n^2), which may result in a “Time Limit Exceeded” error for large inputs.

To optimize this, you should keep track of the minimum price seen so far while scanning the array, and for each price, you calculate the profit you could have made had you sold the stocks at that price (i.e., by subtracting the minimum price from the current price). The maximum of these profits would be your answer. This algorithm works in O(n) time and O(1) space.

Here’s how the optimized code could look like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def maxProfit(self, prices: List[int]) -> int:
    min_price = float('inf')  # initialize min_price as infinity
    max_profit = 0  # initialize max_profit as 0

    for price in prices:
        min_price = min(min_price, price)  # update min_price if current price is lower
        profit = price - min_price  # calculate profit if sold at current price
        max_profit = max(max_profit, profit)  # update max_profit if current profit is higher

    return max_profit

In this code, we are maintaining the min_price and max_profit while traversing through the list, which ensures that we are getting the maximum profit with just one pass (O(n)) through the list, thereby optimizing the time complexity.

Can Anyone tell why time limit exceeding here:

class Solution { public: int maxProfit(vector& prices) { int profit =0; for(int i=0;i<prices.size()-1;i++){ for(int j=i+1;j<prices.size();j++){ if(prices[i]<prices[j]){ int temp= prices[j]-prices[i]; profit= max(profit, temp); } } } return profit; } };

Your current approach has a time complexity of O(n^2) due to the nested for loop, where n is the length of the prices list. For each price in the list, you are comparing it with every other price that comes after it, and this becomes quite costly in terms of time complexity, especially with large inputs, hence resulting in a “Time Limit Exceeded” error.

A better way to approach this problem would be to use a single pass approach, where you keep track of the minimum price and the maximum profit while iterating through the list of prices. This approach reduces the time complexity to O(n), where n is the length of the list.

Here is a C++ solution with an optimized approach:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int min_price = INT_MAX;
        int max_profit = 0;
        for (int i = 0; i < prices.size(); i++) {
            if (prices[i] < min_price)
                min_price = prices[i];
            else if (prices[i] - min_price > max_profit)
                max_profit = prices[i] - min_price;
        }
        return max_profit;
    }
};

In this solution, for each price, we calculate the profit if we were to sell at the current price (i.e., prices[i] - min_price), and update max_profit if the calculated profit is greater. We also update min_price if the current price is less than min_price. This way, we can find the maximum profit with just one pass through the list.

I have tried to solve this problem using C. My solution works for almost all of the TCs. But the problem is that it shows time limit exceeded when the input is so large. So can anyone can help me to optimize my code? Thanks a lot.

`int maxProfit(int* prices, int pricesSize) { int buy_day = 0; int sell_day = 0; int max_profit = 0; int profit = 0;

for (buy_day = 0; buy_day<pricesSize; buy_day++) { sell_day = buy_day + 1; for(sell_day; sell_day<pricesSize; sell_day++) { profit = prices[sell_day] - prices[buy_day]; if (profit > max_profit) { max_profit = profit; } } } return max_profit; }`

Your current approach of using two nested loops to check every possible pair of “buy” and “sell” days is correct in terms of logic, but it has a time complexity of O(n^2), where n is the size of the prices array. This approach can become time-consuming and result in a “Time Limit Exceeded” error when the size of the input is very large.

To optimize your code, you can use a single-pass approach. This approach only requires one loop through the prices array, and hence has a time complexity of O(n). During this single pass, you keep track of the minimum price seen so far (which is the best day to buy) and the maximum profit that can be made (which is the best day to sell).

Here’s the optimized code in C:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
int maxProfit(int* prices, int pricesSize) {
    int min_price = INT_MAX;
    int max_profit = 0;
    for (int i = 0; i < pricesSize; i++) {
        if (prices[i] < min_price)
            min_price = prices[i];
        else if (prices[i] - min_price > max_profit)
            max_profit = prices[i] - min_price;
    }
    return max_profit;
}

In this code, we first initialize min_price to INT_MAX and max_profit to 0. Then, for each price, we check if it’s less than min_price. If it is, we update min_price. If it’s not, we calculate the profit we could have made by selling at that price (prices[i] - min_price), and if this profit is greater than max_profit, we update max_profit. By the end of the loop, max_profit is the maximum profit we can make.

CAN SOMEONE PLS..HELP ME , WHERE M I WRONG? Can we find the solution in this way?](CAN SOMEONE PLS..HELP ME , WHERE M I WRONG? Can we find the solution in this way?)

`class Solution { public: int maxProfit(vector& v) {

vector<int>v1=v;
sort(v1.begin() , v1.end());
int num=0;
int n=v.size();
int front=0;
int end=v.size()-1;
int maxx=INT_MIN;
while(num!=n)
{
    int i=search(v , 0 , n-1 ,  v1[front]);
    int j=search(v , 0 , n-1 ,  v1[end]);
    if(i<j)
    {
        maxx=max(maxx , (v1[end]-v1[front]));
        end=v.size()-1;
        front++;
        num++;
    }
    else if(front==end)
    {
        front++;
        end=v.size()-1;
        num++;
    }
    else
    {
        end--;
    }
}
if(maxx<=0)
return 0;
else 
return maxx;

} int search(vectorarr , int l , int r , int x) { if (r >= l) { int mid = l + (r - l) / 2;

if (arr[mid] == x)
    return mid;

// If element is smaller than mid, then
// it can only be present in left subarray
if (arr[mid] > x)
    return search(arr, l, mid - 1, x);

// Else the element can only be present
// in right subarray
return search(arr, mid + 1, r, x);

} return -1; } };`

Your current approach seems to be sorting the array first, and then trying to find the maximum difference in the sorted array such that the smaller element comes before the larger element in the original array. However, there are some issues with this approach:

  1. Efficiency: The sorting operation itself takes O(n log n) time, and for each element in the sorted array, you are performing a binary search on the original array, which takes O(log n) time. So the overall time complexity of your approach is O(n log n) + O(n log n) = O(n log n), which could be too slow for large inputs. Note that the problem can be solved in O(n) time.

  2. Logic: The sorting operation changes the relative order of the elements, so it’s not guaranteed that for a particular front and end, i will be less than j. As a result, the maxx value may not be updated as expected.

Here is a more efficient and straightforward solution using a single-pass approach:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int min_price = INT_MAX;
        int max_profit = 0;
        for (int i = 0; i < prices.size(); i++) {
            if (prices[i] < min_price)
                min_price = prices[i];
            else if (prices[i] - min_price > max_profit)
                max_profit = prices[i] - min_price;
        }
        return max_profit;
    }
};

In this solution, min_price is the minimum price seen so far (i.e., the best day to buy), and max_profit is the maximum profit that can be made (i.e., the best day to sell). For each price, if it’s less than min_price, min_price is updated. Otherwise, we calculate the profit by selling at that price (prices[i] - min_price), and if this profit is greater than max_profit, max_profit is updated. The function finally returns max_profit, which is the maximum profit that can be made.

Whats wrong with this code? def maxProfit(self, prices: List[int]) -> int: n = len(prices) minimum_num = min(prices) index_min = prices.index(minimum_num) if index_min != n: prices = prices[index_min+1:] if len(prices) != 0: max_num = max(prices) else: max_num = 0 if max_num > minimum_num: return max_num - minimum_num else: return 0 return max_num - minimum_num

it fails for the input [2,4,1], expected output is 2 my output is 0

The issue with your current implementation is that it tries to find the minimum price in the array and then find the maximum price in the array from the index next to the minimum. However, this will fail in cases where the maximum price is not located after the minimum price, but there is another lower price after the maximum. Your input [2,4,1] is a perfect example of this scenario.

In your approach, the minimum price is 1 and it comes after the maximum price 4, but the maximum difference is 2 (4 - 2), not 0 (1 - 1). Therefore, your implementation returns the incorrect output.

Here’s an improved version of your function that correctly finds the maximum difference:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def maxProfit(self, prices: List[int]) -> int:
    min_price = float('inf')  # initialize min_price as infinity
    max_profit = 0  # initialize max_profit as 0

    for price in prices:
        min_price = min(min_price, price)  # update min_price if current price is lower
        profit = price - min_price  # calculate profit if sold at current price
        max_profit = max(max_profit, profit)  # update max_profit if current profit is higher

    return max_profit

In this code, we traverse through the array, keeping track of the minimum price and maximum profit as we go. For each price, we check if it’s lower than our current minimum price and update accordingly. We then calculate the potential profit if we were to sell at the current price, and update our maximum profit if the potential profit is higher.

That is how I understand/digest the one pass approach. Just think yourself as a some one who can change mind at will.

int maxProfit(int* prices, int pricesSize) { /* You buy the stock at day 1 at whatever price. This is ok since you can change your mind later. And this is minimal price so far. */ int min_price = prices[0]; int max_profit = 0; // No profit at day one. int i;

for(i = 1; i < pricesSize; i++) { if(prices[i] < min_price) { /* As days go by. You see a cheaper price. You are kind of regret that you bought at higher price. But there is nothing you can do other than recording the minimal price. / min_price = prices[i]; } else { if(prices[i] - min_price > max_profit) / Now you see a higher price such that if you sell today and bought at the recorded minimal price you will make more profit. You immediately changed your mind :-) */ max_profit = prices[i] - min_price; } }

return max_profit; }

Yes, your understanding of the one-pass approach is correct. As the name suggests, it involves traversing the array of stock prices only once, tracking the minimum price seen so far (as the optimal buy price), and also the maximum profit that can be made (as the optimal sell price).

In essence, we iterate through each price, treating it as the selling price, and we see if we can maximize our profit by selling at this price (assuming we bought at the lowest price we’ve seen up to this point).

It’s like a simulation of a trader who can foresee the prices of the future and would want to maximize their profit under the constraints that they must first buy before they sell. The one-pass approach is efficient (O(n)) and straightforward once you understand the logic behind it.

Your code correctly implements this approach, and it should be able to find the maximum profit for any given array of stock prices.

Why I am getting Time Limit Exceeded here?

int n = prices.size()-1; int minn = INT_MAX, maxx = INT_MIN; int i=0,j=n; while(i<j){ if(prices[i]<minn) minn = prices[i++]; if(prices[j]>maxx) maxx = prices[j–]; } if(maxx-minn>0) return maxx-minn; else return 0;

The issue with your code is that you are trying to simultaneously find the minimum and maximum prices in the array from both ends. However, this is not guaranteed to find the minimum and maximum prices that yield the maximum profit. The maximum profit comes from the maximum difference between the earliest minimum price and the latest maximum price that comes after this minimum. Your approach may miss some potential maximum profits.

Moreover, because your loop only advances when it finds a new minimum from the beginning or a new maximum from the end, it could potentially enter an infinite loop if the array is sorted in increasing or decreasing order.

A better approach would be to use a single-pass traversal from the beginning of the array to the end, keeping track of the minimum price and maximum profit as we go. This ensures that the minimum price comes before the maximum price, and it is guaranteed to finish in a finite amount of time.

Here’s how you could write it in C++:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
int maxProfit(vector<int>& prices) {
    int min_price = INT_MAX;
    int max_profit = 0;
    for (int i = 0; i < prices.size(); i++) {
        if (prices[i] < min_price)
            min_price = prices[i];
        else if (prices[i] - min_price > max_profit)
            max_profit = prices[i] - min_price;
    }
    return max_profit;
}

In this code, we iterate through each price. If the current price is less than our current minimum, we update the minimum. Otherwise, we check if selling at the current price would give us a higher profit than our current maximum profit, and update the maximum profit if so. By the end of the loop, max_profit contains the maximum profit we can make.

The following code I’ve come up with passes all tests except the one. What’s wrong with it? I can’t guess the solution.

class Solution: def maxProfit(self, prices: List[int]) -> int: if len(prices) > 1: # minPrice, minIdx = min(prices), prices.index(min(prices)) minPrice, minIdx = min(prices[:-1]), prices[:-1].index(min(prices[:-1])) maxPrice, maxIdx = max(prices[1:]), 1 + prices[1:].index(max(prices[1:])) else: return 0

    remPricesMin = prices[minIdx:]
    maxPriceMin = max(remPricesMin) if len(remPricesMin) > 0 else minPrice
    diff1 = maxPriceMin - minPrice
    
    remPricesMax = prices[:maxIdx]
    minPriceMax = min(remPricesMax) if len(remPricesMax) > 0 else maxPrice
    diff2 = maxPrice - minPriceMax

    diff = max(diff1, diff2)

    if diff > 0:
        return diff
    else:
        return 0

The problem with your code lies in the logic where you’re trying to find the minimum price and maximum price in the array. The logic you’re using right now is that you’re finding the minimum price from the whole list excluding the last element and the maximum price from the remaining list starting from index 1. This doesn’t always give you the correct minimum and maximum pair for the maximum profit.

Consider the example [1, 2, 4, 2, 5, 7, 2, 4, 9, 0]. In this case, the minimum price is 0 and the maximum price is 9, but buying at 0 and selling at 9 wouldn’t give you the maximum profit because 9 comes before 0. The correct answer would be to buy at 1 and sell at 9, giving a profit of 8.

To fix your code, you can use a single pass approach. In this approach, you keep track of the minimum price you have seen so far and the maximum profit you can get at each point:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        min_price = float('inf')  # initialize min_price as infinity
        max_profit = 0  # initialize max_profit as 0

        for price in prices:
            min_price = min(min_price, price)  # update min_price if current price is lower
            profit = price - min_price  # calculate profit if sold at current price
            max_profit = max(max_profit, profit)  # update max_profit if current profit is higher

        return max_profit

In this code, min_price is the minimum price seen so far (i.e., the best day to buy), and max_profit is the maximum profit that can be made (i.e., the best day to sell). For each price, if it’s less than min_price, min_price is updated. Otherwise, we calculate the profit by selling at that price (price - min_price), and if this profit is greater than max_profit, max_profit is updated. The function finally returns max_profit, which is the maximum profit that can be made.

public class Solution {

public int MaxProfit(int[] prices) {

    Stack<int> stack = new Stack<int>();

    int maxProfit = int.MinValue;

    for (int i = 0; i < prices.Length; i++)
    {
        for (int j = i + 1; j < prices.Length; j++)
        {
            stack.Push(prices[i]);

            if (- stack.Peek() + prices[j] > maxProfit)
            {
                maxProfit = - stack.Pop() + prices[j];
            }
        }
    }

    return maxProfit > 0 ? maxProfit : 0;

} }

Can someone tell me why the code above has a runtime error ‘Out of memory’ and how to fix it?

The problem with your code is that you are using a stack to store every price for each iteration of your nested loop. This causes the stack to grow very large when you have a big input array, eventually leading to an out of memory error.

In fact, you don’t need a stack (or any other additional data structure) to solve this problem. You can just keep track of the minimum price seen so far and the maximum profit you can make.

The following is an optimized version of your code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class Solution {
    public int MaxProfit(int[] prices) {
        int minPrice = int.MaxValue;
        int maxProfit = 0;
        
        for (int i = 0; i < prices.Length; i++) {
            if (prices[i] < minPrice)
                minPrice = prices[i];
            else if (prices[i] - minPrice > maxProfit)
                maxProfit = prices[i] - minPrice;
        }
        
        return maxProfit;
    }
}

In this code, minPrice is the minimum price seen so far (i.e., the best day to buy), and maxProfit is the maximum profit that can be made (i.e., the best day to sell). For each price, if it’s less than minPrice, minPrice is updated. Otherwise, we calculate the profit by selling at that price (price - minPrice), and if this profit is greater than maxProfit, maxProfit is updated. The function finally returns maxProfit, which is the maximum profit that can be made.

one pitfall I always fall into is, trying to calculate more information than required. as this problem I think we need to get the date of buying and selling to determine how to get max profit.

It’s easy to overthink and assume that you need to know the specific buy and sell dates. However, the problem only asks for the maximum profit you can achieve, not when to buy or sell. You’re interested in the difference between the lowest and highest points, with the caveat that the lowest point must come before the highest.

Therefore, your task reduces to finding the smallest number followed by the largest number in the list. With that information, you can calculate the maximum possible profit.

Here’s a simple way to conceptualize it:

  • As you iterate through the array of prices, imagine you are at a specific day.
  • You have two pieces of information:
    • The lowest price you’ve seen up until this day (inclusive). This would be the best day to have bought so far.
    • The highest profit you could have made if you had sold on this day (having bought at the lowest price point you’ve seen).
  • At each day, you update these two pieces of information.
  • By the end of the array, you have the maximum profit you could have made.

The day on which you buy is when you see the lowest price so far, and the day on which you sell is when you see the highest profit. However, you don’t need to keep track of these days if you’re only interested in the maximum profit.

This approach requires only a single pass through the data and a constant amount of space, so it’s quite efficient.

what if in question instead of one transaction there are unlimited transactions are allowed ? Can you please give me a hint or brief idea ?

The problem you are referring to is a variation of the “Best Time to Buy and Sell Stock” problem on LeetCode. In the original problem, you’re only allowed to complete at most one transaction (i.e., buy one and sell one share of the stock). The variation you’re asking about allows for as many transactions as you want (i.e., buy one and sell one share of the stock multiple times).

The key to solving this problem is realizing that the optimal strategy involves making a transaction every time there is a price increase from one day to the next. So, for any two consecutive days, if the price on the second day is higher than the price on the first day, we should make a transaction.

You can implement this strategy in an algorithm as follows:

  1. Initialize a variable profit to 0.
  2. Iterate through the price array from the second element to the last. For each price, if it’s higher than the price on the previous day, add the difference to profit.
  3. Return profit.

Here’s a pseudo-code example:

function maxProfit(prices):
    profit = 0
    for i from 1 to prices.length - 1:
        if prices[i] > prices[i - 1]:
            profit += prices[i] - prices[i - 1]
    return profit

This algorithm essentially accumulates all the positive differences between consecutive days, thus maximizing the total profit. It treats every increase as a separate transaction, which is equivalent to buying on a day and selling on the next day whenever the price increases.

This is in a way an application of Kadane’s algorithm. First get the difference between current - previous. Then apply Kadane’s algo on the result.

Yes, that’s absolutely correct!

For those not familiar, Kadane’s algorithm is a dynamic programming algorithm used to solve the maximum subarray problem, which is the task of finding the contiguous subarray with the largest sum in a one-dimensional array. The solution to the “Best Time to Buy and Sell Stock II” problem, where you can make as many transactions as you like, is somewhat similar to the maximum subarray problem.

However, there’s a slight but significant difference: In the stock problem, we want to find the maximum sum of all positive differences (i.e., all increases in price), regardless of whether they’re contiguous or not, whereas in the maximum subarray problem, we’re looking for the maximum sum of a contiguous subarray.

When you calculate the difference array and apply Kadane’s algorithm, you’re finding the maximum sum of a contiguous subsequence of the difference array. This might not give you the correct answer for the stock problem because you’re allowed to buy and sell on non-contiguous days as well.

Therefore, the correct approach to the “Best Time to Buy and Sell Stock II” problem is to add up all positive differences, without requiring them to be contiguous. This is simpler than applying Kadane’s algorithm, and guarantees that you get the correct answer.

can you please discuss the soln, for what happens if we can (sell and purchase) each transaction atmost k times and you must sell the stock before you buy the next stock

If the problem is extended to allow up to k transactions, the complexity increases, but it can still be solved using dynamic programming.

You’ll need a two-dimensional array profit[t][d], where t is the transaction index (from 0 to k) and d is the day index (from 0 to the number of days - 1). profit[t][d] represents the maximum profit we can get by making at most t transactions up to day d.

You can initialize profit[t][0] to 0 for all t (since you can’t make a profit on the first day), and profit[0][d] to 0 for all d (since you can’t make a profit with 0 transactions).

Then, you’ll iterate over t and d to fill in the rest of the profit array. For each pair (t, d), you have two options:

  1. Don’t make a transaction on day d. In this case, the profit is the same as it was on the previous day, i.e., profit[t][d - 1].

  2. Sell a stock on day d. In this case, you need to find the day to buy the stock that maximizes the profit. Let’s call this day d'. You buy on day d' and sell on day d, and you also get the profit from making t - 1 transactions up to day d' - 1. This gives you a profit of prices[d] - prices[d'] + profit[t - 1][d' - 1]. You’ll take the maximum over all possible d' (from 0 to d - 1).

So, you’ll fill in profit[t][d] as max(profit[t][d - 1], prices[d] - prices[d'] + profit[t - 1][d' - 1] for all d' in [0, d - 1]).

Finally, the maximum profit you can get is profit[k][n - 1], where n is the number of days.

This solution has a time complexity of O(k*n^2) because for each pair (t, d), it iterates over [0, d - 1] to find the best day d' to buy the stock.

The time complexity can be reduced to O(k*n) by keeping track of the maximum value of prices[d'] - profit[t - 1][d' - 1] for all d' in [0, d - 1], and updating it for each d. This value represents the maximum profit you can get by ending your t - 1th transaction on or before day d' - 1 and starting your tth transaction on day d'.

Here is the pseudo code for this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
function maxProfit(prices, k):
    n = len(prices)
    if k > n / 2:
        return quickSolve(prices) # quickSolve() is the function for unlimited transactions

    profit = [[0]*n for _ in range(k+1)]
    for t in range(1, k+1):
        maxDiff = -prices[0]
        for d in range(1, n):
            profit[t][d] = max(profit[t][d - 1], prices[d] + maxDiff)
            maxDiff = max(maxDiff, profit[t - 1][d - 1] - prices[d])
    return profit[k][n - 1]

In this code, maxDiff is the maximum value of profit[t - 1][d' - 1] - prices[d'] for all d' in [0, d - 1]. We update maxDiff for each d to ensure that it always represents the best day d' to buy the stock for the current transaction and day.

What if we want to get all the options to get max profit printed ?

To print all the transaction options for maximum profit, we need to slightly modify our approach. Along with tracking the maximum profit, we need to also track the decisions we made at each point.

After computing the maximum profit table, you can backtrack from profit[k][n-1] to find the transactions. If profit[t][d] is not equal to profit[t][d - 1], it means we made a transaction on day d. We can then find the day d' we bought the stock by searching for d' such that prices[d] - prices[d'] + profit[t - 1][d' - 1] equals profit[t][d]. This is essentially the inverse of the computation we did to fill in the profit array.

This approach can be quite complex and time-consuming because for each transaction, you have to search for the day you bought the stock. An alternative approach is to store the decisions directly in another array during the dynamic programming step.

Here is a rough pseudo code for the entire approach:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function maxProfit(prices, k):
    n = len(prices)
    if k > n / 2:
        return quickSolve(prices) # quickSolve() is the function for unlimited transactions

    profit = [[0]*n for _ in range(k+1)]
    decision = [[0]*n for _ in range(k+1)]  # new decision array
    for t in range(1, k+1):
        maxDiff = -prices[0]
        for d in range(1, n):
            if prices[d] + maxDiff > profit[t][d - 1]:
                profit[t][d] = prices[d] + maxDiff
                decision[t][d] = d  # store the decision of making a transaction on day d
            else:
                profit[t][d] = profit[t][d - 1]
            maxDiff = max(maxDiff, profit[t - 1][d - 1] - prices[d])

    # backtracking to find the transactions
    transactions = []
    d = n - 1
    for t in range(k, 0, -1):
        if decision[t][d] != 0:  # if we made a transaction on day d
            buy_day = decision[t][d]
            sell_day = d
            transactions.append((buy_day, sell_day))  # add the transaction to the list
            d = buy_day - 1  # move to the day before we bought the stock
    return profit[k][n - 1], transactions[::-1]  # reverse the transactions list to get them in chronological order

This code will return the maximum profit as well as the list of transactions. Each transaction is a pair (buy_day, sell_day) indicating the day you bought the stock and the day you sold it.

Please note that this pseudo code is simplified and assumes perfect inputs, so you should add your own error checking and edge case handling where necessary.

For 121. Best Time to Buy and Sell Stock

The solutions all mention a greedy approach, where you keep track of the minimum cost and update it whenever there is a smaller value. Why doesn’t this fail any testcases? I’d imagine something along the lines of [6,12,1,3] would cause those algorithms to fail, no?

This approach doesn’t fail any test cases due to the nature of the problem. The problem asks for the maximum profit we can make from a single buy and sell operation. The best time to buy is always the lowest possible price up to the current point in time, which is why we keep track of the minimum cost.

For your example, [6,12,1,3], this approach correctly identifies that the best time to buy is when the cost is 1. However, it also keeps track of the maximum profit possible up to the current point in time, which includes profits made before we encounter this new minimum.

Let’s break down this example:

  • Initially, the minimum cost is 6, and the maximum profit is 0.
  • Next, we see 12. We update our maximum profit to be max(0, 12 - 6) = 6. Minimum cost remains at 6.
  • Then, we see 1. Now, we update our minimum cost to be 1 since 1 < 6. Our maximum profit is still 6 from before.
  • Finally, we see 3. The maximum profit becomes max(6, 3 - 1) = 6.

So, the algorithm correctly returns 6 as the maximum profit. It’s important to note that the algorithm doesn’t just remember the latest minimum cost, but also the maximum profit it can make with previous minimum costs. So, the greedy approach works perfectly for this problem.