Advertisement
i_love_rao_khushboo

Best Time to Buy and Sell Stock IV

Sep 19th, 2022
1,114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.00 KB | None | 0 0
  1. // Problem link: https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/
  2.  
  3. // Useful Reference(s): --->
  4. // https://medium.com/algorithms-and-leetcode/best-time-to-buy-sell-stocks-on-leetcode-the-ultimate-guide-ce420259b323
  5.  
  6. /*********************************************************************************************************/
  7.  
  8. // Method 1 (Top Down DP - 3D) (using a 3D vector)
  9.  
  10. /* # In this approach our dp is defined by 3 states (that's why 3D DP)
  11.    # State-1(bought): This shows if the stock just previous to current stock was bought or not
  12.                       We will have max 2 possibilities in this, even though we have 3 choices (skip/buy/sell the current stock)
  13.    # State-2(t): This shows the atmost #transactions we can make from current position to the last of prices array.
  14.                  So there will be (k + 1) values for this (0 to k).
  15.    # State-3(pos): It shows the current position of stock prices which we are working on.                  
  16. */
  17.  
  18. #include<bits/stdc++.h>
  19. using namespace std;
  20.  
  21. vector<vector<vector<int>>> dp;
  22.  
  23. int solve(bool bought, int t, int pos, int n, vector<int> &v) {
  24.     // base case
  25.     // if out of bounds or if #transactions = 0, then profit which
  26.     // can be achieved = 0
  27.     if(pos >= n || t == 0) return 0;
  28.    
  29.     // check if already calculated or not
  30.     if(dp[bought][t][pos] != -1) return dp[bought][t][pos];
  31.    
  32.     // Now we have 3 choices (skip, buy or sell the current share according to
  33.     // previous call)
  34.    
  35.     // Case: if we skip the current element
  36.     int ans = solve(bought, t, pos + 1, n, v);
  37.    
  38.     // Case: if we sell the current element
  39.     if(bought) ans = max(ans, v[pos] + solve(false, t - 1, pos + 1, n, v));
  40.    
  41.     // Case: if we buy the current element
  42.     else ans = max(ans, -v[pos] + solve(true, t, pos + 1, n, v));
  43.    
  44.     // return by taking whichever is maximum
  45.     return dp[bought][t][pos] = ans;
  46. }
  47.  
  48. int maxProfit(int k, vector<int> &prices) {
  49.     vector<int> v = prices;
  50.     int n = v.size();
  51.    
  52.     dp.resize(2, vector<vector<int>>(k + 1, vector<int>(n, -1)));
  53.     return solve(false, k, 0, n, v);
  54. }
  55.  
  56. int main()
  57. {
  58.     ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
  59.     srand(chrono::high_resolution_clock::now().time_since_epoch().count());
  60.  
  61.     // #ifndef ONLINE_JUDGE
  62.     //     freopen("input.txt", "r", stdin);
  63.     //     freopen("output.txt", "w", stdout);
  64.     // #endif
  65.  
  66.     vector<int> prices {3, 2, 6, 5, 0, 3};
  67.     int k; k =3;
  68.     cout << maxProfit(k, prices);
  69.  
  70.     return 0;
  71. }
  72.  
  73. // Time complexity:
  74.  
  75. /************************************************************************************************************/
  76.  
  77. // Method 2 (Top Down DP - 3D) (using a unordered_map instead of a 3D table for lookup)
  78. // This method may give TLE in some of the cases as the lookup of a string in the unordered map
  79. // will not take constant time as in Method 1 above.
  80.  
  81. #include<bits/stdc++.h>
  82. using namespace std;
  83.  
  84. unordered_map<string, int> dp;
  85.  
  86. int solve(bool bought, int t, int pos, int n, vector<int> &v) {
  87.     // base case
  88.     // if out of bounds or if #transactions = 0, then profit which
  89.     // can be achieved = 0
  90.     if(pos >= n || t == 0) return 0;
  91.    
  92.     // check if already calculated or not
  93.     string key = to_string(bought) + to_string(t) + to_string(pos);
  94.     if(dp.count(key) != 0) return dp[key];
  95.    
  96.     // Now we have 3 choices (skip, buy or sell the current share according to
  97.     // previous call)
  98.    
  99.     // Case: if we skip the current element
  100.     int ans = solve(bought, t, pos + 1, n, v);
  101.    
  102.     // Case: if we sell the current element
  103.     if(bought) ans = max(ans, v[pos] + solve(false, t - 1, pos + 1, n, v));
  104.    
  105.     // Case: if we buy the current element
  106.     else ans = max(ans, -v[pos] + solve(true, t, pos + 1, n, v));
  107.    
  108.     // return by taking whichever is maximum
  109.     return dp[key] = ans;
  110. }
  111.  
  112. int maxProfit(int k, vector<int> &prices) {
  113.     vector<int> v = prices;
  114.     int n = v.size();
  115.    
  116.     return solve(false, k, 0, n, v);
  117. }
  118.  
  119. int main()
  120. {
  121.     ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
  122.     srand(chrono::high_resolution_clock::now().time_since_epoch().count());
  123.  
  124.     // #ifndef ONLINE_JUDGE
  125.     //     freopen("input.txt", "r", stdin);
  126.     //     freopen("output.txt", "w", stdout);
  127.     // #endif
  128.  
  129.     vector<int> prices {3, 2, 6, 5, 0, 3};
  130.     int k; k = 2;
  131.     cout << maxProfit(k, prices);
  132.  
  133.     return 0;
  134. }
  135.  
  136. // This method is not as efficient in terms of time as compared to Method 1, but it is more efficient
  137. // in terms of space as against Method 1.
  138.  
  139. /************************************************************************************************************/
  140.  
  141. // Method 3 (Bottom up DP - 2D)
  142. // Link for this approach --->
  143. // https://www.youtube.com/watch?v=3YILP-PdEJA
  144.  
  145. #include<bits/stdc++.h>
  146. using namespace std;
  147.  
  148. // dp[i][j] will store the max profit we can gain by performing
  149. // at most i transactions upto the jth day
  150. vector<vector<int>> dp;
  151.  
  152. int solve(int k, int n, vector<int> &v) {
  153.     dp.resize(k + 1, vector<int>(n));
  154.    
  155.     // initialization
  156.     for(int i = 0; i < n; i++) dp[0][i] = 0;
  157.     for(int j = 0; j <= k; j++) dp[j][0] = 0;
  158.    
  159.     for(int i = 1; i <= k; i++) {
  160.         for(int j = 1; j < n; j++) {
  161.             // case when we have already performed at most
  162.             // i transactions upto the (j - 1)th day
  163.             dp[i][j] = dp[i][j - 1];
  164.            
  165.             // case when we have performed at most (i - 1) transactions
  166.             // upto the dth day & we are performing 1 transaction on the
  167.             // jth day
  168.             for(int d = (j - 1); d >= 0; d--) {
  169.                 dp[i][j] = max(dp[i][j], dp[i - 1][d] + v[j] - v[d]);
  170.             }
  171.         }
  172.     }
  173.    
  174.     return dp[k][n - 1];
  175. }
  176.  
  177. int maxProfit(int k, vector<int> &prices) {
  178.     vector<int> v = prices;
  179.     int n = v.size();
  180.     if(n == 0 || k == 0) return 0;
  181.    
  182.     return solve(k, n, v);
  183. }
  184.  
  185. int main()
  186. {
  187.     ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
  188.     srand(chrono::high_resolution_clock::now().time_since_epoch().count());
  189.  
  190.     // #ifndef ONLINE_JUDGE
  191.     //     freopen("input.txt", "r", stdin);
  192.     //     freopen("output.txt", "w", stdout);
  193.     // #endif
  194.  
  195.     vector<int> prices {3, 2, 6, 5, 0, 3};
  196.     int k; k = 2;
  197.     cout << maxProfit(k, prices);
  198.  
  199.     return 0;
  200. }
  201.  
  202. // Time complexity: O(k x n^2)
  203.  
  204. /************************************************************************************************************/
  205.  
  206. // Method 4 (Bottom up DP - 2D)
  207. // This method is just a slight modification of "Method 3" to make it more
  208. // time efficient
  209. // Link for this approach --->
  210. // https://www.youtube.com/watch?v=3YILP-PdEJA
  211.  
  212. #include<bits/stdc++.h>
  213. using namespace std;
  214.  
  215. // dp[i][j] will store the max profit we can gain by performing
  216. // at most i transactions upto the jth day
  217. vector<vector<int>> dp;
  218.  
  219. int solve(int k, int n, vector<int> &v) {
  220.     dp.resize(k + 1, vector<int>(n));
  221.    
  222.     // initialization
  223.     for(int i = 0; i < n; i++) dp[0][i] = 0;
  224.     for(int j = 0; j <= k; j++) dp[j][0] = 0;
  225.    
  226.     int mx;
  227.     for(int i = 1; i <= k; i++) {
  228.         mx = dp[i - 1][0] - v[0];
  229.         for(int j = 1; j < n; j++) {
  230.             // case when we have already performed at most
  231.             // i transactions upto the (j - 1)th day
  232.             dp[i][j] = max(dp[i][j - 1], mx + v[j]);
  233.             mx = max(mx, dp[i - 1][j] - v[j]);
  234.         }
  235.     }
  236.    
  237.     return dp[k][n - 1];
  238. }
  239.  
  240. int maxProfit(int k, vector<int> &prices) {
  241.     vector<int> v = prices;
  242.     int n = v.size();
  243.     if(n == 0 || k == 0) return 0;
  244.    
  245.     return solve(k, n, v);
  246. }
  247.  
  248. int main()
  249. {
  250.     ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
  251.     srand(chrono::high_resolution_clock::now().time_since_epoch().count());
  252.  
  253.     // #ifndef ONLINE_JUDGE
  254.     //     freopen("input.txt", "r", stdin);
  255.     //     freopen("output.txt", "w", stdout);
  256.     // #endif
  257.  
  258.     vector<int> prices {3, 2, 6, 5, 0, 3};
  259.     int k; k = 2;
  260.     cout << maxProfit(k, prices);
  261.  
  262.     return 0;
  263. }
  264.  
  265. // Time complexity: O(k x n)
  266.  
  267. /************************************************************************************************************/
  268.  
  269. // Method 5 (STATE MACHINE DP)
  270. // Link for explanation of this approach --->
  271. // https://www.youtube.com/watch?v=6928FkPhGUA
  272.  
  273. #include<bits/stdc++.h>
  274. using namespace std;
  275.  
  276. int solve(int k, int n, vector<int> &v) {
  277.     // Case 1:
  278.     if(n <= 1 || k == 0) return 0;
  279.    
  280.     // Case 2
  281.     if(2 * k >= n) {
  282.         // in this case simply use the peak-valley approach
  283.         int res = 0;
  284.         for(int i = 1; i < n; i++) {
  285.             if(v[i] > v[i - 1]) res += (v[i] - v[i - 1]);
  286.         }
  287.        
  288.         return res;
  289.     }
  290.    
  291.     // Case 3 (when 2 * k < n)
  292.     // dp[i] is used for remembering the max profit which
  293.     // can be achieved for ith state, (in total there can be atmost
  294.     // (2 * k) states or atmost k transactions
  295.     vector<int> dp(2 * k);
  296.    
  297.     for(int i = 0; i < (2 * k); i++) {
  298.         if(i & 1) dp[i] = 0; // odd numbered states are buy states
  299.         else dp[i] = INT_MIN; // even numbered states are sell states
  300.     }
  301.    
  302.     // j is used for iterating over the days
  303.     // i is used for iterating over the all (2 * k) states
  304.     // dp[i] upto a particular j will store the the max profit which
  305.     // can be gained by performing at most k transactions(having 2 * k states)
  306.     // by considering the first (j + 1) elements (from v[0] to v[j])
  307.     for(int j = 0; j < n; j++) {
  308.         for(int i = 0; i < (2 * k); i++) {
  309.             // special case
  310.             if(i == 0) dp[i] = max(dp[i], -v[j]);
  311.            
  312.             // when i is the sell state
  313.             else if(i & 1) dp[i] = max(dp[i], dp[i - 1] + v[j]);
  314.            
  315.             // when i is the buy state
  316.             else dp[i] = max(dp[i], dp[i - 1] - v[j]);
  317.         }
  318.     }
  319.    
  320.     return dp[2 * k - 1];
  321. }
  322.  
  323. int maxProfit(int k, vector<int> &prices) {
  324.     vector<int> v = prices;
  325.     int n = v.size();
  326.    
  327.     return solve(k, n, v);
  328. }
  329.  
  330. int main()
  331. {
  332.     ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
  333.     srand(chrono::high_resolution_clock::now().time_since_epoch().count());
  334.  
  335.     // #ifndef ONLINE_JUDGE
  336.     //     freopen("input.txt", "r", stdin);
  337.     //     freopen("output.txt", "w", stdout);
  338.     // #endif
  339.  
  340.     vector<int> prices {3, 2, 6, 5, 0, 3};
  341.     int k; k = 2;
  342.     cout << maxProfit(k, prices);
  343.  
  344.     return 0;
  345. }
  346.  
  347. // NOTE: In Case 3, we don't perform 'k' transactions [since (2 * k < n)], the transactions will be
  348. //       skipped & previous values in the dp[] will be stored.  
  349.  
  350. // Time complexity: O(k x n)
  351.  
  352. /************************************************************************************************************/
  353.  
  354. // Method 6 (STATE MACHINE DP) (Just a slight modification of the Method 5)
  355. // Instead of using a single dp array as in Method 2, in this method, 2 dp
  356. // arrays are considered.
  357.  
  358. #include<bits/stdc++.h>
  359. using namespace std;
  360.  
  361. int solve(int k, int n, vector<int> &v) {
  362.     // Case 1:
  363.     if(n <= 1 || k == 0) return 0;
  364.    
  365.     // Case 2
  366.     if(2 * k >= n) {
  367.         // in this case simply use the peak-valley approach
  368.         int res = 0;
  369.         for(int i = 1; i < n; i++) {
  370.             if(v[i] > v[i - 1]) res += (v[i] - v[i - 1]);
  371.         }
  372.        
  373.         return res;
  374.     }
  375.    
  376.     // Case 3 (when 2 * k < n)
  377.     vector<int> dp_buy(k), dp_sell(k);
  378.    
  379.     for(int i = 1; i < k; i++) {
  380.         dp_buy[i] = INT_MIN;
  381.         dp_sell[i] = 0;
  382.     }
  383.    
  384.     dp_buy[0] = -v[0];
  385.     dp_sell[0] = 0;
  386.    
  387.     for(int j = 0; j < n; j++) {
  388.         for(int i = 0; i < k; i++) {
  389.             if(i == 0) {
  390.                 dp_buy[i] = max(dp_buy[i], -v[j]);
  391.                 dp_sell[i] = max(dp_sell[i], dp_buy[i] + v[j]);
  392.             }
  393.            
  394.             else {
  395.                 dp_buy[i] = max(dp_buy[i], dp_sell[i - 1] - v[j]);
  396.                 dp_sell[i] = max(dp_sell[i], dp_buy[i] + v[j]);
  397.             }
  398.         }
  399.     }
  400.    
  401.     return dp_sell[k - 1];
  402. }
  403.  
  404. int maxProfit(int k, vector<int> &prices) {
  405.     vector<int> v = prices;
  406.     int n = v.size();
  407.    
  408.     return solve(k, n, v);
  409. }
  410.  
  411. int main()
  412. {
  413.     ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
  414.     srand(chrono::high_resolution_clock::now().time_since_epoch().count());
  415.  
  416.     // #ifndef ONLINE_JUDGE
  417.     //     freopen("input.txt", "r", stdin);
  418.     //     freopen("output.txt", "w", stdout);
  419.     // #endif
  420.  
  421.     vector<int> prices {3, 2, 6, 5, 0, 3};
  422.     int k; k = 2;
  423.     cout << maxProfit(k, prices);
  424.  
  425.     return 0;
  426. }
  427.  
  428. // NOTE: In Case 3, we don't perform 'k' transactions [since (2 * k < n)], the transactions will be
  429. //       skipped & previous values in the dp_sell[] & dp_buy[] will be stored.  
  430.  
  431. // Time complexity: O(k x n)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement