Skip to content

Commit 7c90a0f

Browse files
committed
2026-03-29 23:42
1 parent c49ee98 commit 7c90a0f

10 files changed

Lines changed: 207 additions & 12 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module best-time-to-buy-and-sell-stock-ii
2+
3+
go 1.26.1
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package main
2+
3+
import "fmt"
4+
5+
func maxProfit(prices []int) int {
6+
if len(prices) <= 1 {
7+
return 0
8+
}
9+
profit := 0
10+
low := prices[0]
11+
12+
for i := 0; i < len(prices); i++ {
13+
if prices[i] > low {
14+
profit += prices[i] - low
15+
}
16+
low = prices[i]
17+
}
18+
return profit
19+
}
20+
21+
func main() {
22+
fmt.Println(maxProfit([]int{7,1,5,3,6,4}))
23+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module best-time-to-buy-and-sell-stock
2+
3+
go 1.26.1
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package main
2+
3+
import "fmt"
4+
5+
func maxProfit(prices []int) int {
6+
if len(prices) <= 1 {
7+
return 0
8+
}
9+
maxProfit := 0
10+
lowPrice := prices[0]
11+
for i := 1; i < len(prices); i++ {
12+
if prices[i] - lowPrice > maxProfit {
13+
maxProfit = prices[i] - lowPrice
14+
}
15+
if lowPrice > prices[i] {
16+
lowPrice = prices[i]
17+
}
18+
}
19+
return maxProfit
20+
}
21+
22+
func main() {
23+
fmt.Println(maxProfit([]int{0}))
24+
fmt.Println(maxProfit([]int{1}))
25+
fmt.Println(maxProfit([]int{7,1,5,3,6,4}))
26+
fmt.Println(maxProfit([]int{7,6,4,3,1}
27+
}

src/p/leetcode/best-time-to-buy-and-sell-stock/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,11 @@ impl Solution {
1414
return max
1515
}
1616

17-
// DP1
1817
pub fn max_profit2(prices: Vec<i32>) -> i32 {
1918
let mut max = 0;
2019
let mut profit = vec![0; prices.len()];
2120
for i in 1..prices.len() {
22-
for j in (0..i).rev() {
21+
for j in (0..i).rev() { // 很关键,保证新的低价格被考虑到
2322
if prices[i] >= prices[j] {
2423
profit[i] = profit[j] + (prices[i] - prices[j]);
2524
if profit[i] > max {
@@ -59,5 +58,7 @@ mod tests {
5958

6059
assert_eq!(Solution::max_profit2(vec![1, 2, 3]), 2);
6160
assert_eq!(Solution::max_profit2(vec! [7,1,5,3,6,4]), 5);
61+
assert_eq!(Solution::max_profit2(vec! [9, 100, 1, 101]), 100);
62+
assert_eq!(Solution::max_profit3(vec! [9, 100, 1, 101]), 100);
6263
}
6364
}

src/p/leetcode/index.rst

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -247,26 +247,32 @@ Best Time to Buy and Sell Stock
247247
:id: best-time-to-buy-and-sell-stock
248248
:diffculty: Easy
249249
:language: rust
250-
:key: 动态规划
251-
:date: 2021-07-07
250+
:key: 数组
251+
:date: 2021-07-07 2026-03-29
252252
:reference: https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/bao-li-mei-ju-dong-tai-gui-hua-chai-fen-si-xiang-b/
253253

254254
写了三个版本:
255255

256256
暴力
257257
TLE,每次 `i+1..prices.len()` 的回溯有大量荣誉计算,复杂度为 :math:`O(n!)`
258258

259-
DP1
260-
其实不太算 DP,参考里给出了非常 DP 的解法。
261-
`profit[i]` 第 i 天卖出股票的最大正收益(亏本不卖)。以为状态转移方程是 `profit[i] = profit[j] + (prices[i] - prices[j])`, where `j < i && prices[j] <= prices[i]` 。复杂度依然为 :math:`O(n!)` ,只是有几率避免冗余计算,勉强 AC 但时间上只超过了 8% 的选手,有问题。
259+
暴力 + 稍微剪枝
260+
内层循环的 `(0..i).rev()` 很重要,确保新出现的低价被计算到。
261+
复杂度依然为 :math:`O(n!)` ,只是有几率避免冗余计算,勉强 AC 但时间上只超过了 8% 的选手,有问题。
262262

263263
.. note:: 实际上 `profit[i]` 可以只从 `profit[i-1]` 推断,见下
264264

265-
DP2
265+
DP
266266
更好的状态转移方程是 `profit[i] = max(profit[i-1] + (prices[i] - prices[i-1]), 0)` 。复杂度为 :math:`O(n)` ,超过了 85%+ 的选手,够了。
267267

268268
从题意上看,方程的意思是:在第 i-1 天我们已经取得了能取得的最大收益,那第 i 天也应该参考第 i-1 天的购入时机,如果亏本了,则不购入。
269269

270+
2026-03-29: 看起来不太对。
271+
272+
记录低价
273+
只买卖一次,所以记录下 maxProfit 和 lowPrice,每次只看
274+
max(maxProfit, price[i] - lowPrice) 即可,遇到 `price[i] < lowPrice` 要及时更新。
275+
270276
Invert Binary Tree
271277
------------------
272278

@@ -286,12 +292,12 @@ Best Time to Buy and Sell Stock II
286292

287293
.. leetcode:: _
288294
:id: best-time-to-buy-and-sell-stock-ii
289-
:diffculty: Easy
295+
:diffculty: Medium
290296
:language: rust
291-
:key: 动态规划
292-
:date: 2021-07-07
297+
:key: 贪心
298+
:date: 2021-07-07 2026-03-29
293299

294-
:leetcode:`Best Time to Buy and Sell Stock` 的一个简单变体,允许多次买卖,没啥好说
300+
:leetcode:`Best Time to Buy and Sell Stock` 的一个简单变体,允许多次买卖,贪心即可,每次有价差则卖出
295301

296302
Best Time to Buy and Sell Stock III
297303
-----------------------------------
@@ -965,3 +971,29 @@ i 位置的元素往右挪动 k 个位置,被修改的下标序列会组成一
965971
`[i, (i+k)%n (i+2k)%n, ... i]`。存在 `(i+x*k)%n == i`,即 `(x*k)%n == 0`。
966972

967973
.. todo:: 环的数目为 `gcd(n, k)`
974+
975+
Jump Game
976+
---------
977+
978+
.. leetcode:: _
979+
:id: jump-game
980+
:diffculty: Easy
981+
:language: go
982+
:key: 贪心
983+
:date: 2026-03-29
984+
985+
Jump Game II
986+
------------
987+
988+
.. leetcode:: _
989+
:id: jump-game-ii
990+
:diffculty: Medium
991+
:language: go
992+
:key: 贪心
993+
:date: 2026-03-29
994+
995+
`解法 1 <https://medium.com/@william31525/leetcode-45-jump-game-2-294a21f5baba>`_
996+
非常好懂,`for i in (0..n)` 找出能越过终点(`i+nums[i]>=n-1`)的地方,那里就是最小步数再 + 1 就能达到终点的地方。时间复杂度稍高
997+
998+
解法 2
999+
其实和 1 一样,但利用 `farest` 和 `end` 两个变量配合消除了内部循环,保证 `O(n)`

src/p/leetcode/jump-game-ii/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module jump-game-ii
2+
3+
go 1.26.1
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
// https://medium.com/@william31525/leetcode-45-jump-game-2-294a21f5baba
8+
func jump(nums []int) int {
9+
if len(nums) <= 2 {
10+
return len(nums) - 1
11+
}
12+
13+
var footprints []int
14+
for {
15+
lastStep := -1
16+
for i := 0; i < len(nums); i++ {
17+
if i + nums[i] >= len(nums) - 1 {
18+
lastStep = i
19+
footprints = append(footprints, lastStep)
20+
break
21+
}
22+
}
23+
if lastStep == 0 {
24+
break
25+
}
26+
nums = nums[:lastStep+1]
27+
}
28+
return len(footprints)
29+
}
30+
31+
func max(a, b int) int {
32+
if a > b {
33+
return a
34+
}
35+
return b
36+
}
37+
38+
func jump2(nums []int) int {
39+
if len(nums) <= 2 {
40+
return len(nums) - 1
41+
}
42+
43+
farest := 0
44+
end := 0
45+
step := 0
46+
47+
for i := 0; i < len(nums); i++ {
48+
farest = max(farest, i+nums[i])
49+
if i == end {
50+
end = farest
51+
step++
52+
}
53+
if end >= len(nums) - 1 {
54+
break
55+
}
56+
}
57+
return step
58+
}
59+
60+
61+
func main() {
62+
fmt.Println(jump([]int{2,3,1,1,4}))
63+
fmt.Println(jump([]int{1,1,1,1,1}))
64+
fmt.Println(jump([]int{3,1,0}))
65+
fmt.Println(jump([]int{2,3,1}))
66+
fmt.Println(jump([]int{2,3,1,4}))
67+
fmt.Println(jump([]int{2,3,1,1,4}))
68+
69+
fmt.Println("===")
70+
71+
fmt.Println(jump2([]int{2,3,1,1,4}))
72+
fmt.Println(jump2([]int{1,1,1,1,1}))
73+
fmt.Println(jump2([]int{3,1,0}))
74+
fmt.Println(jump2([]int{2,3,1}))
75+
fmt.Println(jump2([]int{2,3,1,4}))
76+
fmt.Println(jump2([]int{2,3,1,1,4}))
77+
}

src/p/leetcode/jump-game/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module jump-game
2+
3+
go 1.26.1

src/p/leetcode/jump-game/main.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package main
2+
3+
import "fmt"
4+
5+
func canJump(nums []int) bool {
6+
if len(nums) <= 1 {
7+
return true
8+
}
9+
max := 0;
10+
for i := 0; i < len(nums); i++ {
11+
if max < i {
12+
break
13+
}
14+
if max < i+nums[i] {
15+
max = i+nums[i]
16+
}
17+
}
18+
return max >= len(nums) - 1
19+
}
20+
21+
func main() {
22+
fmt.Println(canJump([]int{3,2,1,0,4}))
23+
}

0 commit comments

Comments
 (0)