From 2eacdbbb8a5eb032d685bff0ac72c2b04088425b Mon Sep 17 00:00:00 2001 From: Samavarta Date: Mon, 9 Mar 2026 01:29:05 +0530 Subject: [PATCH 1/3] Update buy-and-sell-crypto.md Add DP explanation for buy-and-sell stock --- articles/buy-and-sell-crypto.md | 108 ++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/articles/buy-and-sell-crypto.md b/articles/buy-and-sell-crypto.md index e01550d4f..38b8c25c9 100644 --- a/articles/buy-and-sell-crypto.md +++ b/articles/buy-and-sell-crypto.md @@ -586,6 +586,114 @@ impl Solution { --- + +## Another intuitive Dynamic Programming Method :- +> Keeping track of two variables : index and a boolean canBuy +> canBuy ensures if the stock can be bought or not -> if the stock can be bought it basically implies that the stock has not been sold. But if stock cannot be bought means that it has to be sold. So, we create two cases using the canBuy variable. +> For case 1 where we can buy a stock we check for the current indexed element if it is better to buy or not buy just recursing using two variables namely : 'take' for if we want to take the current stock and 'skip' for if we do not want to take the current stock. +> Else we either sell the stock or hold it. > This process will only be done once as per the question. +> But due do recursion we are actually exploring all possibilites, that gives exponential time. In order to bring down the time complexity we cache(Dynamic Programming) our results in a dp table so that we do not repeat any subproblems(standard procedure of Dynamic Programming to take care of overlapping subproblems) +> two states for DP as we are updating both index and canBuy variables Code in CPP :- + +##Recursion + Memoization :- +``` +class Solution { +public: + int n; + vector> dp; + int f(int i, int canBuy, vector& prices){ + if(i == n){ + return 0; + } + if(dp[i][canBuy] != -1 || i+1 > n) return dp[i][canBuy]; //reduces the number of calls + + //case 1 : we can buy it; + if(canBuy == 1){ + int take = f(i+1, 0, prices) - prices[i]; + + int skip = f(i+1, 1, prices); + + return dp[i][canBuy] = max(take, skip); + + } + //case 2 : selling the stock (i.e., cannot buy) + else{ + int sell = prices[i]; + + int hold = f(i + 1, 0, prices); + + return dp[i][canBuy] = max(sell, hold); + } + } + int maxProfit(vector& prices) { + + + n = prices.size(); + dp.assign(n+1, vector(2, -1)); canBuy can have only two states, either yes or no + + return f(0, 1, prices); + return dp[0][1]; + + } +}; + +``` +#Complexities +>Time Complexity = O(2*n) -> O(n) +>>Space Complexity = O( (n* 2) -> O(n) + recursive stack [ O(n) ] + + + + + + +## Equivalent Tabulation Method +>> >Just write the above recursive calls in terms of Dp indices in an iterative manner. +>> > >Reduces Resursive Stack Overhead. + + +``` +class Solution { +public: + int n; + vector> dp; + int maxProfit(vector& prices) { + + + n = prices.size(); + dp.assign(n+1, vector(2, 0)); + //tabulation + for(int i = n-1;i>=0;i--){ + int take = dp[i+1][0] - prices[i]; + + int skip = dp[i+1][1]; + + dp[i][1] = max(take, skip); + + int sell = prices[i]; + + int keep = dp[i+1][0]; + + dp[i][0] = max(sell , keep); + } + return dp[0][1]; + + } +}; + +``` +#Complexities +>Time Complexity = O(2*n) -> O(n) +>Space Complexity = O( (n+1)* 2) -> O(n) (No recursive stack) + + + + + + + + + ## Common Pitfalls ### Selling Before Buying From e30a3f21260fef44b432718a609f607c24245a75 Mon Sep 17 00:00:00 2001 From: Samavarta Date: Mon, 9 Mar 2026 01:30:51 +0530 Subject: [PATCH 2/3] Update buy-and-sell-crypto.md Add DP explanation for buy-and-sell stock --- articles/buy-and-sell-crypto.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/articles/buy-and-sell-crypto.md b/articles/buy-and-sell-crypto.md index 38b8c25c9..974d1ea2f 100644 --- a/articles/buy-and-sell-crypto.md +++ b/articles/buy-and-sell-crypto.md @@ -587,6 +587,8 @@ impl Solution { --- + + ## Another intuitive Dynamic Programming Method :- > Keeping track of two variables : index and a boolean canBuy > canBuy ensures if the stock can be bought or not -> if the stock can be bought it basically implies that the stock has not been sold. But if stock cannot be bought means that it has to be sold. So, we create two cases using the canBuy variable. From 3ce017d04cb2d88818ebe91125226d4dac3592cf Mon Sep 17 00:00:00 2001 From: Samavarta Date: Mon, 9 Mar 2026 01:33:18 +0530 Subject: [PATCH 3/3] Update buy-and-sell-crypto.md Added another Intuitive DP solution. --- articles/buy-and-sell-crypto.md | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/articles/buy-and-sell-crypto.md b/articles/buy-and-sell-crypto.md index 974d1ea2f..353352dfa 100644 --- a/articles/buy-and-sell-crypto.md +++ b/articles/buy-and-sell-crypto.md @@ -591,12 +591,22 @@ impl Solution { ## Another intuitive Dynamic Programming Method :- > Keeping track of two variables : index and a boolean canBuy -> canBuy ensures if the stock can be bought or not -> if the stock can be bought it basically implies that the stock has not been sold. But if stock cannot be bought means that it has to be sold. So, we create two cases using the canBuy variable. + +> canBuy ensures if the stock can be bought or not -> if the stock can be bought it basically implies that the stock has not been sold. But if stock cannot be + +> bought means that it has to be sold. So, we create two cases using the canBuy variable. + > For case 1 where we can buy a stock we check for the current indexed element if it is better to buy or not buy just recursing using two variables namely : 'take' for if we want to take the current stock and 'skip' for if we do not want to take the current stock. + > Else we either sell the stock or hold it. > This process will only be done once as per the question. + > But due do recursion we are actually exploring all possibilites, that gives exponential time. In order to bring down the time complexity we cache(Dynamic Programming) our results in a dp table so that we do not repeat any subproblems(standard procedure of Dynamic Programming to take care of overlapping subproblems) + > two states for DP as we are updating both index and canBuy variables Code in CPP :- + + + ##Recursion + Memoization :- ``` class Solution { @@ -631,10 +641,9 @@ public: n = prices.size(); - dp.assign(n+1, vector(2, -1)); canBuy can have only two states, either yes or no + dp.assign(n+1, vector(2, -1)); //canBuy can have only two states, either yes or no return f(0, 1, prices); - return dp[0][1]; } };