Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit edff769

Browse files
authored
feat: add go solution to lc problem: No.0403 (#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)

AltStyle によって変換されたページ (->オリジナル) /