Skip to content

Commit 71c0aea

Browse files
committed
Reorganize the note of dynamic programming; fix some typos
1 parent b0bf24d commit 71c0aea

9 files changed

+201
-67
lines changed

leetcode/121.best-time-to-buy-and-sell-stock.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,8 @@ fun maxProfit(prices: IntArray): Int {
88
var lowestPrice = prices[0]
99
var maxProfit = 0
1010
for (i in 1 until prices.size) {
11-
if (prices[i] < lowestPrice) {
12-
lowestPrice = prices[i]
13-
} else {
14-
maxProfit = max(maxProfit, prices[i] - lowestPrice)
15-
}
11+
lowestPrice = min(lowestPrice, prices[i])
12+
maxProfit = max(maxProfit, prices[i] - lowestPrice)
1613
}
1714
return maxProfit
1815
}

leetcode/198.house-robber.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ fun rob(nums: IntArray): Int {
6363
if (nums.size == 1) return nums[0]
6464
if (nums.size == 2) return max(nums[0], nums[1])
6565

66-
val dp = IntArray(nums.size)
6766
var p2 = nums[0]
6867
var p1 = max(nums[0], nums[1])
6968
for (i in 2 until nums.size) {

leetcode/509.fibonacci-number.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,23 @@ fun fib(n: Int): Int {
1919
}
2020
}
2121
```
22+
23+
```python
24+
def fib(self, n: int) -> int:
25+
memo = {}
26+
def helper(k: int) -> int:
27+
if k <= 1:
28+
return k
29+
30+
if k in memo:
31+
return memo[k]
32+
33+
memo[k] = helper(k - 1) + helper(k - 2)
34+
return memo[k]
35+
36+
return helper(n)
37+
```
38+
2239
* **Time Complexity**: `O(n)`.
2340
* **Space Complexity**: `O(n)`.
2441

@@ -35,6 +52,17 @@ fun fib(n: Int): Int {
3552
return dp[n]
3653
}
3754
```
55+
56+
```python
57+
def fib(self, n: int) -> int:
58+
if n <= 1:
59+
return n
60+
dp = [0, 1] + [0] * (n - 1)
61+
for i in range(2, n + 1):
62+
dp[i] = dp[i - 1] + dp[i - 2]
63+
return dp[n]
64+
```
65+
3866
* **Time Complexity**: `O(n)`.
3967
* **Space Complexity**: `O(n)`.
4068

@@ -53,5 +81,18 @@ fun fib(n: Int): Int {
5381
return fib
5482
}
5583
```
84+
85+
```python
86+
def fib(self, n: int) -> int:
87+
if n <= 1:
88+
return n
89+
n1, n2 = 1, 0
90+
result = 0
91+
for i in range(2, n + 1):
92+
result = n1 + n2
93+
n2 = n1
94+
n1 = result
95+
return result
96+
```
5697
* **Time Complexity**: `O(n)`.
5798
* **Space Complexity**: `O(1)`.
Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,35 @@
11
## [746. Min Cost Climbing Stairs](https://leetcode.com/problems/min-cost-climbing-stairs/)
22

3-
The `dp[i]` represents the cost **to** i-th step:
4-
* To 0-th step and 1-th step cost 0.
5-
* The cost to i-th step will be the minimum of to (i - 1)-th cost + (i - 1) cost or to (i - 2)-th cost + (i - 2) cost.
3+
We start either from index `0` or `1`, and find the min cost when reaching `n-th` step. There are two way to represent the states:
4+
5+
```js
6+
# to(i) = min(to(i - 1) + cost[i - 1], to(i - 2) + cost[i - 2])
7+
# from(i) = cost[i] + min(from(i - 1), from(i - 2))
8+
```
9+
10+
### `To` State
11+
12+
The `to(i)` / `dp[i]` represents the cost **to** i-th step:
13+
* To `0` or `1` step cost 0, because we start from index `0` or `1`.
14+
* The cost to `i-th` step will be the minimum of `to(i - 1) + cost[i - 1]` and `to(i - 2) + cost[i - 2]`.
615

716
```kotlin
17+
// Recursive with memoization
18+
private val memo = hashMapOf<Int, Int>()
19+
820
fun minCostClimbingStairs(cost: IntArray): Int {
9-
if (cost.size == 2) return min(cost[0], cost[1])
21+
return to(cost, cost.size)
22+
}
23+
24+
private fun to(cost: IntArray, i: Int): Int {
25+
if (i == 0 || i == 1) return 0
26+
if (memo.containsKey(i)) return memo[i]!!
27+
memo[i] = min(to(cost, i - 1) + cost[i - 1], to(cost, i - 2) + cost[i - 2])
28+
return memo[i]!!
29+
}
1030

31+
// Bottom-Up DP
32+
fun minCostClimbingStairs(cost: IntArray): Int {
1133
val n = cost.size
1234
val dp = IntArray(n + 1)
1335
dp[0] = 0
@@ -19,26 +41,27 @@ fun minCostClimbingStairs(cost: IntArray): Int {
1941
}
2042
```
2143

22-
Or we can represent `dp[i]` to be the cost that we pay in order to climb **from** i-th step. That is, to climbing from i-th step, we have to pay `dp[i] = cost[i] + min(dp[i - 1], dp[i - 2])`.
44+
### `From` State
45+
Or we can represent `dp[i]` to be the cost that we pay in order to climb **from** `i-th` step. We have to pay `dp[i] = cost[i] + min(dp[i - 1], dp[i - 2])`.
2346

2447
```kotlin
48+
// Time Complexity: O(n)
49+
// Space Complexity: O(n)
2550
fun minCostClimbingStairs(cost: IntArray): Int {
2651
val n = cost.size
2752
val dp = IntArray(n + 1)
2853
dp[0] = cost[0]
2954
dp[1] = cost[1]
30-
for (i in 2..n) {
55+
for (i in 2 until n) {
3156
dp[i] = cost[i] + min(dp[i - 1], dp[i - 2])
3257
}
58+
// To n-th step, we can either start from n - 1 or n - 2.
3359
return min(dp[i - 1], dp[i - 2])
3460
}
35-
```
3661

37-
* **Time Complexity**: `O(n)` for one for-loop.
38-
* **Space Complexity**: `O(n)` for `dp` array.
39-
40-
### Bottom-DP (Space Optimization)
41-
```kotlin
62+
// Space Optimization
63+
// Time Complexity: O(n)
64+
// Space Complexity: O(1)
4265
fun minCostClimbingStairs(cost: IntArray): Int {
4366
if (cost.size == 2) return min(cost[0], cost[1])
4467

@@ -54,5 +77,23 @@ fun minCostClimbingStairs(cost: IntArray): Int {
5477
}
5578
```
5679

57-
* **Time Complexity**: `O(n)` for one for-loop.
58-
* **Space Complexity**: `O(1)`.
80+
```python
81+
def minCostClimbingStairs(self, cost: List[int]) -> int:
82+
n = len(cost)
83+
# dp[i] = the cost from i-th step
84+
dp = [cost[0], cost[1]] + [0] * (n - 2)
85+
for i in range(2, n):
86+
dp[i] = cost[i] + min(dp[i - 1], dp[i - 2])
87+
return min(dp[n - 1], dp[n - 2])
88+
89+
# Space Optimization
90+
def minCostClimbingStairs(self, cost: List[int]) -> int:
91+
n = len(cost)
92+
# dp[i] = the cost from i-th step
93+
n1, n2 = cost[0], cost[1]
94+
for i in range(2, n):
95+
result = cost[i] + min(n1, n2)
96+
n1 = n2
97+
n2 = result
98+
return min(n1, n2)
99+
```

media/assembly-line-scheduling.png

-28.6 KB
Binary file not shown.

topics/complexity.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,14 @@ fun insertSort(A) { // ---- Times ----
7878
This worst running time can expressed as `a*n^2 + b*n + c`, it's a **quadratic function** of `n`.
7979

8080
We shall usually conccentrate on the worst-case running time, because of the three reasons:
81-
1. It's the upper bound of running time for any input, it gives us a guarantee that the algorithm will never tak any longer.
81+
1. It's the upper bound of running time for any input, it gives us a guarantee that the algorithm will never take any longer.
8282
2. For some algorithm, the worst case occurs fairly often.
8383
3. The "average case" is often roughly as bad as the worst case.
8484

8585
We expect that the same algorithm running on a fast machine will run faster than the same algorithm on a slow one, however, we'd like to be able to compare without worrying about how fast the machine is, so we compare the running time based on *asymptotic performance* (the abstraction way) relative to the input size.
8686

8787
## Asymptotic Notation
88-
When look at input sizes large engough to make only the order of growth of the running time relevant, we use *asymptotic notation* to express the **rate of growth** of an algorithm's running time in terms of the input size `n`.
88+
When we look at input sizes large engough to make only the order of growth of the running time relevant, we use *asymptotic notation* to express the **rate of growth** of an algorithm's running time in terms of the input size `n`.
8989

9090
For the worst-case running time of *insert sort* is `a*n^2 + b*n + c`, what we care about is the **order of growth**, we therefore consider:
9191

0 commit comments

Comments
 (0)