Skip to content

Commit dda96a1

Browse files
authored
Merge pull request #14 from advpetc/dp-pattern
Dp pattern + Streaming system reading note
2 parents 60ae2b2 + 455afe4 commit dda96a1

File tree

3 files changed

+382
-64
lines changed

3 files changed

+382
-64
lines changed
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Distinct Ways
2+
3+
**Statement**
4+
5+
Given a target find a number of distinct ways to reach the target.
6+
7+
**Approach**
8+
9+
Sum all possible ways to reach the current state.
10+
11+
`routes[i] = routes[i-1] + routes[i-2], ... , + routes[i-k]`
12+
13+
Generate sum for all values in the target and return the value for the target.
14+
15+
**Top-Down**
16+
17+
```c++
18+
for (int j = 0; j < ways.size(); ++j) {
19+
result += topDown(target - ways[j]);
20+
}
21+
return memo[/*state parameters*/] = result;
22+
```
23+
24+
**Bottom-Up**
25+
```c++
26+
for (int i = 1; i <= target; ++i) {
27+
for (int j = 0; j < ways.size(); ++j) {
28+
if (ways[j] <= i) {
29+
dp[i] += dp[i - ways[j]];
30+
}
31+
}
32+
}
33+
34+
return dp[target];
35+
```
36+
37+
## 0070. Climbing Stairs
38+
39+
You are climbing a staircase. It takes `n` steps to reach the top.
40+
41+
Each time you can either climb `1` or `2` steps. In how many distinct ways can you climb to the top?
42+
43+
**Example 1:**
44+
45+
```
46+
Input: n = 2
47+
Output: 2
48+
Explanation: There are two ways to climb to the top.
49+
1. 1 step + 1 step
50+
2. 2 steps
51+
52+
```
53+
54+
**Example 2:**
55+
56+
```
57+
Input: n = 3
58+
Output: 3
59+
Explanation: There are three ways to climb to the top.
60+
1. 1 step + 1 step + 1 step
61+
2. 1 step + 2 steps
62+
3. 2 steps + 1 step
63+
64+
```
65+
66+
**Constraints:**
67+
68+
- `1 <= n <= 45`
69+
70+
`dp[i]`: number of ways to reach `i` th starcase. So `dp[i] = dp[i - 1] + dp[i - 2]`
71+
72+
Since we are only using two variables: `dp[i - 1]` and `dp[i - 2]`, we can reduce them to two variables:
73+
```c++
74+
class Solution {
75+
public:
76+
int climbStairs(int n) {
77+
if (n == 1) return 1;
78+
else if (n == 2) return 2;
79+
int one = 1, two = 2;
80+
int res = 0;
81+
for (int i = 3; i <= n; ++i) {
82+
res = one + two;
83+
one = two;
84+
two = res;
85+
}
86+
return res;
87+
}
88+
};
89+
```

docs/Leetcode/topics/dp-patterns/min-max-path.md

Lines changed: 19 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ You are given an integer array `cost` where `cost[i]` is the cost of `ith` step
88

99
You can either start from the step with index `0`, or the step with index `1`.
1010

11-
Return *the minimum cost to reach the top of the floor*.
11+
Return _the minimum cost to reach the top of the floor_.
1212

1313
**Example 1:**
1414

@@ -35,8 +35,6 @@ Explanation: You will start at index 0.
3535
The total cost is 6.
3636
```
3737

38-
39-
4038
**Constraints:**
4139

4240
- `2 <= cost.length <= 1000`
@@ -46,8 +44,8 @@ The total cost is 6.
4644

4745
```c++
4846
for (int i = 2; i <= n; ++i) {
49-
// on last step, there is no need to proceed further.
50-
dp[i] = min(dp[i-1], dp[i-2]) + (i == n ? 0 : cost[i]);
47+
// on last step, there is no need to proceed further.
48+
dp[i] = min(dp[i-1], dp[i-2]) + (i == n ? 0 : cost[i]);
5149
}
5250
return dp[n]
5351
```
@@ -70,8 +68,6 @@ Given a `m x n` `grid` filled with non-negative numbers, find a path from top le
7068

7169
**Note:** You can only move either down or right at any point in time.
7270

73-
74-
7571
**Example 1:**
7672

7773
![img](https://assets.leetcode.com/uploads/2020/11/05/minpath.jpg)
@@ -89,8 +85,6 @@ Input: grid = [[1,2,3],[4,5,6]]
8985
Output: 12
9086
```
9187

92-
93-
9488
**Constraints:**
9589

9690
- `m == grid.length`
@@ -106,20 +100,18 @@ for (int i = 1; i < n; ++i) {
106100
grid[i][j] = min(grid[i-1][j], grid[i][j-1]) + grid[i][j];
107101
}
108102
}
109-
103+
110104
return grid[n-1][m-1]
111105
```
112106

113107
## 0322. Coin Change
114108

115109
You are given an integer array `coins` representing coins of different denominations and an integer `amount` representing a total amount of money.
116110

117-
Return *the fewest number of coins that you need to make up that amount*. If that amount of money cannot be made up by any combination of the coins, return `-1`.
111+
Return _the fewest number of coins that you need to make up that amount_. If that amount of money cannot be made up by any combination of the coins, return `-1`.
118112

119113
You may assume that you have an infinite number of each kind of coin.
120114

121-
122-
123115
**Example 1:**
124116

125117
```
@@ -142,8 +134,6 @@ Input: coins = [1], amount = 0
142134
Output: 0
143135
```
144136

145-
146-
147137
**Constraints:**
148138

149139
- `1 <= coins.length <= 12`
@@ -166,19 +156,18 @@ return dp[amount];
166156
#### Why this cannot be solved by greedy algorithm?
167157

168158
Exception:
159+
169160
> But for some coin sets, there are sums for which the greedy algorithm fails. For example, for the set {1, 15, 25} and the sum 30, the greedy algorithm first chooses 25, leaving a remainder of 5, and then five 1s for a total of six coins. But the solution with the minimal number of coins is to choose 15 twice.
170161
171162
> In any case where there is no coin whose value, when added to the lowest denomination, is lower than twice that of the denomination immediately less than it, the greedy algorithm works.
172-
i.e. {1,2,3} works because [1,3] and [2,2] add to the same value however {1, 15, 25} doesn't work because (for the change 30) 15+15>25+1
163+
> i.e. {1,2,3} works because [1,3] and [2,2] add to the same value however {1, 15, 25} doesn't work because (for the change 30) 15+15>25+1
173164
174165
## 0931. Minimum Falling Path Sum
175166

176-
Given an `n x n` array of integers `matrix`, return *the **minimum sum** of any **falling path** through* `matrix`.
167+
Given an `n x n` array of integers `matrix`, return _the **minimum sum** of any **falling path** through_ `matrix`.
177168

178169
A **falling path** starts at any element in the first row and chooses the element in the next row that is either directly below or diagonally left/right. Specifically, the next element from position `(row, col)` will be `(row + 1, col - 1)`, `(row + 1, col)`, or `(row + 1, col + 1)`.
179170

180-
181-
182171
**Example 1:**
183172

184173
![img](https://assets.leetcode.com/uploads/2021/11/03/failing1-grid.jpg)
@@ -199,8 +188,6 @@ Output: -59
199188
Explanation: The falling path with a minimum sum is shown.
200189
```
201190

202-
203-
204191
**Constraints:**
205192

206193
- `n == matrix.length == matrix[i].length`
@@ -238,9 +225,7 @@ The passes allow that many days of consecutive travel.
238225
239226
- For example, if we get a **7-day** pass on day `2`, then we can travel for `7` days: `2`, `3`, `4`, `5`, `6`, `7`, and `8`.
240227
241-
Return *the minimum number of dollars you need to travel every day in the given list of days*.
242-
243-
228+
Return _the minimum number of dollars you need to travel every day in the given list of days_.
244229
245230
**Example 1:**
246231
@@ -265,8 +250,6 @@ On day 31, you bought a 1-day pass for costs[0] = $2 which covered day 31.
265250
In total, you spent $17 and covered all the days of your travel.
266251
```
267252
268-
269-
270253
**Constraints:**
271254
272255
- `1 <= days.length <= 365`
@@ -296,9 +279,7 @@ There is only one character `'A'` on the screen of a notepad. You can perform tw
296279
- Copy All: You can copy all the characters present on the screen (a partial copy is not allowed).
297280
- Paste: You can paste the characters which are copied last time.
298281

299-
Given an integer `n`, return *the minimum number of operations to get the character* `'A'` *exactly* `n` *times on the screen*.
300-
301-
282+
Given an integer `n`, return _the minimum number of operations to get the character_ `'A'` _exactly_ `n` _times on the screen_.
302283

303284
**Example 1:**
304285

@@ -318,8 +299,6 @@ Input: n = 1
318299
Output: 0
319300
```
320301

321-
322-
323302
**Constraints:**
324303

325304
- `1 <= n <= 1000`
@@ -356,12 +335,10 @@ return s;
356335

357336
## 0279. Perfect Squares
358337

359-
Given an integer `n`, return *the least number of perfect square numbers that sum to* `n`.
338+
Given an integer `n`, return _the least number of perfect square numbers that sum to_ `n`.
360339

361340
A **perfect square** is an integer that is the square of an integer; in other words, it is the product of some integer with itself. For example, `1`, `4`, `9`, and `16` are perfect squares while `3` and `11` are not.
362341

363-
364-
365342
**Example 1:**
366343

367344
```
@@ -378,8 +355,6 @@ Output: 2
378355
Explanation: 13 = 4 + 9.
379356
```
380357

381-
382-
383358
**Constraints:**
384359

385360
- `1 <= n <= 10^4`
@@ -411,9 +386,7 @@ We are playing a game with the stones. On each turn, we choose any two stones an
411386
412387
At the end of the game, there is **at most one** stone left.
413388
414-
Return *the smallest possible weight of the left stone*. If there are no stones left, return `0`.
415-
416-
389+
Return _the smallest possible weight of the left stone_. If there are no stones left, return `0`.
417390
418391
**Example 1:**
419392
@@ -434,8 +407,6 @@ Input: stones = [31,26,33,21,40]
434407
Output: 5
435408
```
436409
437-
438-
439410
**Constraints:**
440411
441412
- `1 <= stones.length <= 30`
@@ -461,12 +432,10 @@ int lastStoneWeightII(vector<int>& stones) {
461432

462433
## 0120. Triangle
463434

464-
Given a `triangle` array, return *the minimum path sum from top to bottom*.
435+
Given a `triangle` array, return _the minimum path sum from top to bottom_.
465436

466437
For each step, you may move to an adjacent number of the row below. More formally, if you are on index `i` on the current row, you may move to either index `i` or index `i + 1` on the next row.
467438

468-
469-
470439
**Example 1:**
471440

472441
```
@@ -487,17 +456,13 @@ Input: triangle = [[-10]]
487456
Output: -10
488457
```
489458

490-
491-
492459
**Constraints:**
493460

494461
- `1 <= triangle.length <= 200`
495462
- `triangle[0].length == 1`
496463
- `triangle[i].length == triangle[i - 1].length + 1`
497464
- `-104 <= triangle[i][j] <= 104`
498465

499-
500-
501466
**Follow up:** Could you do this using only `O(n)` extra space, where `n` is the total number of rows in the triangle?
502467

503468
dp[i]: min cost from bottom to i-th row
@@ -519,12 +484,10 @@ int minimumTotal(vector<vector<int>>& triangle) {
519484
520485
You are given an array of binary strings `strs` and two integers `m` and `n`.
521486
522-
Return *the size of the largest subset of `strs` such that there are **at most*** `m` `0`*'s and* `n` `1`*'s in the subset*.
487+
Return \*the size of the largest subset of `strs` such that there are **at most\*** `m` `0`_'s and_ `n` `1`_'s in the subset_.
523488
524489
A set `x` is a **subset** of a set `y` if all elements of `x` are also elements of `y`.
525490
526-
527-
528491
**Example 1:**
529492
530493
```
@@ -543,8 +506,6 @@ Output: 2
543506
Explanation: The largest subset is {"0", "1"}, so the answer is 2.
544507
```
545508
546-
547-
548509
**Constraints:**
549510
550511
- `1 <= strs.length <= 600`
@@ -556,7 +517,7 @@ My dp[i][j] means with i zeros and j ones, what is the max strings to be chosen
556517
557518
1. choose current string means dp[i-# of zero for current string][j - # of one for current string] + 1.
558519
2. not choose current string means dp[i][j] which means there is nothing changed as previous state.
559-
Why it has to start from m, n and decrease to 1 (or making sure there is at least # of 0 or 1 spots left in our case)? Because it prevents invalid counting. As we can see, our dp[m][n] is going to be updated sz times, and before we calculate i - zero[k] and j - one[k], they has to be valid. If we start from 0 and increase to m, n, these values will never be updated beforehand.
520+
Why it has to start from m, n and decrease to 1 (or making sure there is at least # of 0 or 1 spots left in our case)? Because it prevents invalid counting. As we can see, our dp[m][n] is going to be updated sz times, and before we calculate i - zero[k] and j - one[k], they has to be valid. If we start from 0 and increase to m, n, these values will never be updated beforehand.
560521
561522
```c
562523
int findMaxForm(vector<string>& strs, int m, int n) {
@@ -585,9 +546,7 @@ int findMaxForm(vector<string>& strs, int m, int n) {
585546

586547
## 0221. Maximal Square
587548

588-
Given an `m x n` binary `matrix` filled with `0`'s and `1`'s, *find the largest square containing only* `1`'s *and return its area*.
589-
590-
549+
Given an `m x n` binary `matrix` filled with `0`'s and `1`'s, _find the largest square containing only_ `1`'s _and return its area_.
591550

592551
**Example 1:**
593552

@@ -614,25 +573,21 @@ Input: matrix = [["0"]]
614573
Output: 0
615574
```
616575

617-
618-
619576
**Constraints:**
620577

621578
- `m == matrix.length`
622579
- `n == matrix[i].length`
623580
- `1 <= m, n <= 300`
624581
- `matrix[i][j]` is `'0'` or `'1'`.
625582

626-
627-
628583
Here the`dp[i][j]`the same as `matrix[i][j]`, and it means the maximum width of the square that includes `matrix[i][j]` as the right down side of the resulting square. To expand the area to any directions (right, down), we check the `matrix[i][j-1]`, `matrix[i-1][j]` and `matrix[i-1][j-1]` and choose the minimal from them. The final answer is the maximum `matrix[i][j] * matrix[i][j]` from all the values we have filled.
629584

630585
```c++
631586
for (int i = 0; i < m; ++i) {
632587
for (int j = 0; j < n; ++j) {
633588
if (matrix[i][j] == '0' || i == 0 || j == 0) continue;
634-
matrix[i][j] = min({matrix[i][j - 1] - '0',
635-
matrix[i - 1][j] - '0',
589+
matrix[i][j] = min({matrix[i][j - 1] - '0',
590+
matrix[i - 1][j] - '0',
636591
matrix[i - 1][j - 1] - '0'}) + '1';
637592
res = max(res, matrix[i][j] - '0');
638593
}
@@ -649,5 +604,5 @@ return res * res;
649604
[link](../../../0174.-Dungeon-Game)
650605

651606
## 0871. Minimum Number of Refueling Stops
652-
[link](../../../0871.-Minimum-Number-of-Refueling-Stops)
653607

608+
[link](../../../0871.-Minimum-Number-of-Refueling-Stops)

0 commit comments

Comments
 (0)