|
| 1 | +import java.util.*; |
| 2 | + |
| 3 | +/** |
| 4 | + * Say you have an array for which the ith element is the price of a given |
| 5 | + * stock on day i. |
| 6 | + * |
| 7 | + * Design an algorithm to find the maximum profit. You may complete at most k |
| 8 | + * transactions. |
| 9 | + * |
| 10 | + * Note: |
| 11 | + * You may not engage in multiple transactions at the same time (ie, you must |
| 12 | + * sell the stock before you buy again). |
| 13 | + * |
| 14 | + * Tags: DP |
| 15 | + */ |
| 16 | +class BestTimeStock4 { |
| 17 | + |
| 18 | + public static void main(String[] args) { |
| 19 | + // 2, [3,2,6,5,0,3] |
| 20 | + // 2, [3,3,5,0,0,3,1,4] |
| 21 | + BestTimeStock4 b = new BestTimeStock4(); |
| 22 | + int[] A = new int[]{3,3,5,0,0,3,1,4}; |
| 23 | + int[] B = new int[]{3,2,6,5,0,3}; |
| 24 | + System.out.println(b.maxProfitOpt(2, A)); |
| 25 | + System.out.println(b.maxProfit(2, A)); |
| 26 | + System.out.println(b.maxProfitOpt(2, B)); |
| 27 | + System.out.println(b.maxProfit(2, B)); |
| 28 | + } |
| 29 | + |
| 30 | + /** |
| 31 | + * DP, bottom-up, O(kn) Time, O(n) Space |
| 32 | + * If k >= n/2, we can have transactions any time, O(n). |
| 33 | + * dp[k][i+1] represents the max profit of using [0, i] and k transactions |
| 34 | + * It can be dp[k-1][i+1](add 1 more transaction changes nothing) |
| 35 | + * It can be dp[k][i](prices[i] changes nothing) |
| 36 | + * It can be prices[i] + max(dp[k-1][j] - prices[j]), 0 <= j < i |
| 37 | + * means prices[i] will change the max profit, find the biggest from k-1 |
| 38 | + * transacions and add prices[i] |
| 39 | + * dp[k][i+1] = max(dp[k-1][i+1], dp[k][i], prices[i] + max(dp[k-1][j] - |
| 40 | + * prices[j])), (0 <= j < i) |
| 41 | + */ |
| 42 | + public int maxProfitOpt(int k, int[] prices) { |
| 43 | + if (prices == null || prices.length < 2 || k == 0) return 0; |
| 44 | + int n = prices.length; |
| 45 | + int res = 0; |
| 46 | + if (k >= n / 2) { // as many transactions as possible |
| 47 | + for (int i = 1; i < n; i++) { |
| 48 | + if (prices[i] > prices[i - 1]) res += prices[i] - prices[i - 1]; |
| 49 | + } |
| 50 | + return res; |
| 51 | + } |
| 52 | + int[] cur = new int[n+1]; |
| 53 | + for (int i = 1; i <= k; i++) { |
| 54 | + int curMax = Integer.MIN_VALUE; |
| 55 | + for (int j = 0; j < n; j++) { |
| 56 | + int temp = cur[j+1]; |
| 57 | + cur[j+1] = Math.max(Math.max(cur[j+1], cur[j]), prices[j] + curMax); |
| 58 | + System.out.print(curMax + "|"); |
| 59 | + curMax = Math.max(curMax, temp - prices[j]); |
| 60 | + System.out.print(curMax + "\n"); |
| 61 | + } |
| 62 | + System.out.println(Arrays.toString(cur)); |
| 63 | + } |
| 64 | + return cur[n]; |
| 65 | + } |
| 66 | + |
| 67 | + /** |
| 68 | + * DP, bottom-up, O(kn) Time, O(kn) Space |
| 69 | + */ |
| 70 | + public int maxProfit(int k, int[] prices) { |
| 71 | + if (prices == null || prices.length < 2 || k == 0) return 0; |
| 72 | + int n = prices.length; |
| 73 | + int res = 0; |
| 74 | + if (k >= n / 2) { |
| 75 | + for (int i = 1; i < n; i++) { |
| 76 | + if (prices[i] > prices[i - 1]) res += prices[i] - prices[i - 1]; |
| 77 | + } |
| 78 | + return res; |
| 79 | + } |
| 80 | + int[][] dp = new int[k+1][n+1]; |
| 81 | + for (int i = 1; i <= k; i++) { |
| 82 | + int curMax = Integer.MIN_VALUE; |
| 83 | + for (int j = 0; j < n; j++) { |
| 84 | + dp[i][j+1] = Math.max(Math.max(dp[i-1][j+1], dp[i][j]), prices[j] + curMax); |
| 85 | + curMax = Math.max(curMax, dp[i-1][j] - prices[j]); |
| 86 | + } |
| 87 | + } |
| 88 | + return dp[k][n]; |
| 89 | + } |
| 90 | +} |
0 commit comments