Skip to content

Commit edff769

Browse files
authored
feat: add go solution to lc problem: No.0403 (doocs#863)
No.0403.Frog Jump
1 parent b0e52a6 commit edff769

File tree

3 files changed

+166
-2
lines changed

3 files changed

+166
-2
lines changed

solution/0400-0499/0403.Frog Jump/README.md

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,23 @@
4343

4444
<!-- 这里可写通用的实现逻辑 -->
4545

46-
动态规划,用 `dp[i][k]` 表示最后一次跳跃为 `k` 个单位时,能否到达 `i` ,定义 base case 为 `dp[0][0] = True`(起点在下标 0)。
46+
**方法一:动态规划**
4747

48-
因为 “青蛙上一步跳跃了 `k` 个单位,那么它接下来的跳跃距离只能选择为 `k - 1``k``k + 1` 个单位”,所以 `dp[j][k - 1], dp[j][k], dp[j][k + 1]` 中有任一为真,即可从 `j` 跳跃到 `i`
48+
动态规划转移方程如下:
49+
50+
$$
51+
dp[i][k] = dp[j][k-1] || dp[j][k] || dp[j][k+1]
52+
$$
53+
54+
其中 `dp[i][k]` 表示最后一次跳跃为 `k` 个单位时,能否到达 `i`,定义 base case 为 `dp[0][0] = True`(起点在下标 0)。
55+
56+
对于从 `j` 跳到 `i` 的青蛙,因为跳跃的距离确定为 `k` 个单位,所以根据题意最后一次跳跃到达 `j` 的跳跃距离只能选择为 `k - 1``k``k + 1` 个单位,故只要 `dp[j][k - 1], dp[j][k], dp[j][k + 1]` 中有任一为 `True`,即可从 `j` 跳跃到 `i`
57+
58+
**方法二:回溯+剪枝**
59+
60+
这是最直观的解题思路。显然青蛙在第 `1` 个石子的起始跳跃距离为 `1`,对于第 `2` 个石子,根据题意很容易得到青蛙的跳跃距离只能是 `0、1 或 2`。依次类推,可以得到青蛙在第 `i` 个石子可能的跳跃距离集合,借助这个思路验证当青蛙在 `i` 处跳跃距离为集合之一时是否可以刚好过河,如不能过河继续验证其他取值即可。
61+
62+
注意为避免提交超时,需要添加一个辅助变量减少重复搜索。
4963

5064
<!-- tabs:start -->
5165

@@ -97,6 +111,68 @@ class Solution {
97111
}
98112
```
99113

114+
### **Go**
115+
116+
动态规划:
117+
118+
```go
119+
func canCross(stones []int) bool {
120+
n := len(stones)
121+
dp := make([][]bool, n)
122+
for i := 0; i < n; i++ {
123+
dp[i] = make([]bool, n)
124+
}
125+
dp[0][0] = true
126+
127+
for i := 1; i < n; i++ {
128+
for j := 0; j < i; j++ {
129+
k := stones[i] - stones[j]
130+
// 第 j 个石子上至多只能跳出 j+1 的距离
131+
if k > j+1 {
132+
continue
133+
}
134+
dp[i][k] = dp[j][k-1] || dp[j][k] || dp[j][k+1]
135+
if i == n-1 && dp[i][k] {
136+
return true
137+
}
138+
}
139+
}
140+
return false
141+
}
142+
```
143+
144+
回溯+剪枝:
145+
146+
```go
147+
func canCross(stones []int) bool {
148+
n := len(stones)
149+
help := make(map[int]map[int]bool)
150+
var dfs func(start, step int) bool
151+
152+
dfs = func(start, step int) bool {
153+
if start >= n-1 {
154+
return true
155+
}
156+
157+
if _, ok := help[start]; !ok {
158+
help[start] = make(map[int]bool)
159+
}
160+
if v, ok := help[start][step]; ok {
161+
return v
162+
}
163+
for i := start + 1; i < n; i++ {
164+
if stones[start]+step == stones[i] {
165+
help[start][step] = dfs(i, step-1) || dfs(i, step) || dfs(i, step+1)
166+
return help[start][step]
167+
}
168+
}
169+
help[start][step] = false
170+
return false
171+
}
172+
return dfs(0, 1)
173+
}
174+
```
175+
100176
### **...**
101177

102178
```

solution/0400-0499/0403.Frog Jump/README_EN.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,14 @@
3939

4040
## Solutions
4141

42+
**Approach 1: Dynamic Programming**
43+
4244
DP, use `dp[i][k]` to indicate whether `i` can be reached when the last jump was `k` units, and define the base case as `dp[0][0] = True` (starting point is at index 0).
4345

4446
Because "the frog's last jump was `k` units, its next jump must be either `k - 1`, `k`, or `k + 1` units", so if any of `dp[j][k-1], dp[j][k], dp[j][k + 1]` is true, frog can jump from `j` to `i`.
4547

48+
**Approach 2: Backtracking**
49+
4650
<!-- tabs:start -->
4751

4852
### **Python3**
@@ -89,6 +93,67 @@ class Solution {
8993
}
9094
```
9195

96+
### **Go**
97+
98+
dp:
99+
100+
```go
101+
func canCross(stones []int) bool {
102+
n := len(stones)
103+
dp := make([][]bool, n)
104+
for i := 0; i < n; i++ {
105+
dp[i] = make([]bool, n)
106+
}
107+
dp[0][0] = true
108+
109+
for i := 1; i < n; i++ {
110+
for j := 0; j < i; j++ {
111+
k := stones[i] - stones[j]
112+
if k > j+1 {
113+
continue
114+
}
115+
dp[i][k] = dp[j][k-1] || dp[j][k] || dp[j][k+1]
116+
if i == n-1 && dp[i][k] {
117+
return true
118+
}
119+
}
120+
}
121+
return false
122+
}
123+
```
124+
125+
dfs:
126+
127+
```go
128+
func canCross(stones []int) bool {
129+
n := len(stones)
130+
help := make(map[int]map[int]bool)
131+
var dfs func(start, step int) bool
132+
133+
dfs = func(start, step int) bool {
134+
if start >= n-1 {
135+
return true
136+
}
137+
138+
if _, ok := help[start]; !ok {
139+
help[start] = make(map[int]bool)
140+
}
141+
if v, ok := help[start][step]; ok {
142+
return v
143+
}
144+
for i := start + 1; i < n; i++ {
145+
if stones[start]+step == stones[i] {
146+
help[start][step] = dfs(i, step-1) || dfs(i, step) || dfs(i, step+1)
147+
return help[start][step]
148+
}
149+
}
150+
help[start][step] = false
151+
return false
152+
}
153+
return dfs(0, 1)
154+
}
155+
```
156+
92157
### **...**
93158

94159
```
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
func canCross(stones []int) bool {
2+
n := len(stones)
3+
dp := make([][]bool, n)
4+
for i := 0; i < n; i++ {
5+
dp[i] = make([]bool, n)
6+
}
7+
dp[0][0] = true
8+
9+
for i := 1; i < n; i++ {
10+
for j := 0; j < i; j++ {
11+
k := stones[i] - stones[j]
12+
// 第 j 个石子上至多只能跳出 j+1 的距离
13+
if k > j+1 {
14+
continue
15+
}
16+
dp[i][k] = dp[j][k-1] || dp[j][k] || dp[j][k+1]
17+
if i == n-1 && dp[i][k] {
18+
return true
19+
}
20+
}
21+
}
22+
return false
23+
}

0 commit comments

Comments
 (0)