Skip to content

Commit 66ebe0f

Browse files
committed
✨ new post: leetcode-188
1 parent c326400 commit 66ebe0f

3 files changed

Lines changed: 130 additions & 0 deletions

File tree

_posts/2022-09-11-leetcode-188.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
---
2+
title: "[Leetcode] 188. Best Time to Buy and Sell Stock IV explained"
3+
excerpt: "Leetcode daily challenge 2022 september 11th solution"
4+
header:
5+
overlay_image: /public/images/problem-solving-common-header.png
6+
tags:
7+
- Dynamic programming
8+
last_modified_at: 2022-09-11T01:24:08+09:00
9+
---
10+
11+
<a href="https://leetcode.com/">
12+
<img src="/public/images/leetcode-logo.jpeg"/>
13+
</a>
14+
15+
## Problem
16+
17+
<a href="https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/">
18+
<img src="/public/images/leetcode-188.png"/>
19+
</a>
20+
21+
<br/>
22+
23+
## Key Idea
24+
25+
This is a typical dynamic programming problem.
26+
27+
Before we get into main point, suppose we have unlimited chance of transaction (`k` $$= \infty$$. `k` $$= \frac{k}2$$ is large enough).
28+
Then, we may perform transaction whenever we discover price higher than yesterday, and that becomes our maximum profit.
29+
Please note the `quickSolve` method in solution.
30+
31+
Now let's get into our main discussion.
32+
33+
We define a recursive helper function `findMaxProfit`, which finds maximum profit with `k` transactions in interval `[0, endIdx]`, inclusive.
34+
35+
```java
36+
private int findMaxProfit(final int[] prices, int endIdx, int k) {
37+
if (endIdx == -1 || k == 0) return 0;
38+
39+
int maxProfit= 0;
40+
for (int i=0; i < endIdx; ++i) {
41+
if (prices[i] < prices[endIdx]) {
42+
int spotProfit= prices[endIdx] - prices[i];
43+
maxProfit= Math.max(maxProfit, findMaxProfit(prices, i-1, k-1) + spotProfit);
44+
} else {
45+
maxProfit= Math.max(maxProfit, findMaxProfit(prices, i, k));
46+
}
47+
}
48+
return maxProfit;
49+
}
50+
```
51+
<br/>
52+
53+
But that's not good enough.
54+
We compute `maxProfit` value over and over, which is known as overlapping subproblems in dp.
55+
56+
Below is the optimal version of `findMaxProfit`, using `memoization`.
57+
58+
```java
59+
private int findMaxProfit(final int[] prices, int endIdx, int k) {
60+
if (endIdx == -1 || k == 0) return 0;
61+
62+
if (cache[endIdx][k] != -1) return cache[endIdx][k];
63+
cache[endIdx][k]= 0;
64+
for (int i=0; i < endIdx; ++i) {
65+
if (prices[i] < prices[endIdx]) {
66+
int spotProfit= prices[endIdx] - prices[i];
67+
cache[endIdx][k]= Math.max(cache[endIdx][k], findMaxProfit(prices, i-1, k-1) + spotProfit);
68+
} else {
69+
cache[endIdx][k]= Math.max(cache[endIdx][k], findMaxProfit(prices, i, k));
70+
}
71+
}
72+
return cache[endIdx][k];
73+
}
74+
```
75+
76+
We now can simply return `findMaxProfit(prices, n-1, k)`.
77+
78+
- Time: $$O(n^2)$$
79+
- Space: $$O(n{\cdot}k)$$
80+
81+
<br/>
82+
83+
## Implementation
84+
85+
<img src="/public/images/leetcode-188-result.png"/>
86+
87+
```java
88+
/**
89+
* author: jooncco
90+
* written: 2022. 9. 11. Tue. 02:04:14 [UTC+9]
91+
**/
92+
93+
class Solution {
94+
private int n;
95+
private int[][] cache;
96+
97+
public int maxProfit(int k, int[] prices) {
98+
n= prices.length;
99+
if (k >= n/2) return quickSolve(prices, k);
100+
101+
cache= new int[n+1][k+1];
102+
for (int[] row : cache) Arrays.fill(row, -1);
103+
return findMaxProfit(prices, n-1, k);
104+
}
105+
106+
private int findMaxProfit(final int[] prices, int endIdx, int k) {
107+
if (endIdx == -1 || k == 0) return 0;
108+
109+
if (cache[endIdx][k] != -1) return cache[endIdx][k];
110+
cache[endIdx][k]= 0;
111+
for (int i=0; i < endIdx; ++i) {
112+
if (prices[i] < prices[endIdx]) {
113+
int spotProfit= prices[endIdx] - prices[i];
114+
cache[endIdx][k]= Math.max(cache[endIdx][k], findMaxProfit(prices, i-1, k-1) + spotProfit);
115+
} else {
116+
cache[endIdx][k]= Math.max(cache[endIdx][k], findMaxProfit(prices, i, k));
117+
}
118+
}
119+
return cache[endIdx][k];
120+
}
121+
122+
private int quickSolve(final int[] prices, int k) {
123+
int maxProfit= 0;
124+
for (int i=1; i < n; ++i) {
125+
if (prices[i] > prices[i-1]) maxProfit += prices[i] - prices[i-1];
126+
}
127+
return maxProfit;
128+
}
129+
}
130+
```
39.2 KB
Loading

public/images/leetcode-188.png

227 KB
Loading

0 commit comments

Comments
 (0)