46
46
47
47
** 方法一:记忆化搜索**
48
48
49
- 时间复杂度 $O(k^2)$。
49
+ 我们设计一个函数 $dfs(i, j)$,表示当前位置距离目标位置的距离为 $i$,还剩 $j$ 步,有多少种方法到达目标位置。那么答案就是 $dfs(abs(startPos - endPos), k)$。
50
+
51
+ 函数 $dfs(i, j)$ 的计算方式如下:
52
+
53
+ - 如果 $i \gt j$ 或者 $j \lt 0$,说明当前位置距离目标位置的距离大于剩余步数,或者剩余步数为负数,此时无法到达目标位置,返回 $0$;
54
+ - 如果 $j = 0$,说明剩余步数为 $0$,此时只有当前位置距离目标位置的距离为 $0$ 时才能到达目标位置,否则无法到达目标位置,返回 $1$ 或者 $0$;
55
+ - 否则,当前位置距离目标位置的距离为 $i$,还剩 $j$ 步,那么有两种方法到达目标位置:
56
+ - 向左移动一步,此时当前位置距离目标位置的距离为 $i + 1$,还剩 $j - 1$ 步,方法数为 $dfs(i + 1, j - 1)$;
57
+ - 向右移动一步,此时当前位置距离目标位置的距离为 $abs(i - 1)$,还剩 $j - 1$ 步,方法数为 $dfs(abs(i - 1), j - 1)$;
58
+ - 最后,返回两种方法的和对 $10^9 + 7$ 取余的结果。
59
+
60
+ 为了避免重复计算,我们使用记忆化搜索,即使用一个二维数组 $f$ 记录函数 $dfs(i, j)$ 的结果,当函数 $dfs(i, j)$ 被调用时,如果 $f[ i] [ j ] $ 不为 $-1$,则直接返回 $f[ i] [ j ] $,否则计算 $f[ i] [ j ] $ 的值,并返回 $f[ i] [ j ] $。
61
+
62
+ 时间复杂度 $O(k^2)$,空间复杂度 $O(k^2)$。其中 $k$ 为题目给定的步数。
50
63
51
64
<!-- tabs:start -->
52
65
58
71
class Solution :
59
72
def numberOfWays (self , startPos : int , endPos : int , k : int ) -> int :
60
73
@cache
61
- def dfs (d , k ) :
62
- if k < 0 or abs (d) > k :
74
+ def dfs (i : int , j : int ) -> int :
75
+ if i > j or j < 0 :
63
76
return 0
64
- if k == 0 :
65
- return d == 0
66
- res = dfs(d - 1 , k - 1 ) + dfs(d + 1 , k - 1 )
67
- return res % (10 ** 9 + 7 )
77
+ if j == 0 :
78
+ return 1 if i == 0 else 0
79
+ return (dfs(i + 1 , j - 1 ) + dfs(abs (i - 1 ), j - 1 )) % mod
68
80
81
+ mod = 10 ** 9 + 7
69
82
return dfs(abs (startPos - endPos), k)
70
83
```
71
84
@@ -75,34 +88,27 @@ class Solution:
75
88
76
89
``` java
77
90
class Solution {
78
- private static final int MOD = (int ) 1e9 + 7 ;
79
- private int [][] f = new int [3010 ][3010 ];
80
- private int j;
91
+ private Integer [][] f;
92
+ private final int mod = (int ) 1e9 + 7 ;
81
93
82
94
public int numberOfWays (int startPos , int endPos , int k ) {
83
- startPos += 1000 ;
84
- endPos += 1000 ;
85
- for (var e : f) {
86
- Arrays . fill(e, - 1 );
87
- }
88
- j = endPos;
89
- return dfs(startPos, k);
95
+ f = new Integer [k + 1 ][k + 1 ];
96
+ return dfs(Math . abs(startPos - endPos), k);
90
97
}
91
98
92
- private int dfs (int i , int k ) {
93
- if (Math . abs(i - j) > k ) {
99
+ private int dfs (int i , int j ) {
100
+ if (i > j || j < 0 ) {
94
101
return 0 ;
95
102
}
96
- if (f[i][k] != - 1 ) {
97
- return f[i][k] ;
103
+ if (j == 0 ) {
104
+ return i == 0 ? 1 : 0 ;
98
105
}
99
- if (k == 0 ) {
100
- return i == j ? 1 : 0 ;
106
+ if (f[i][j] != null ) {
107
+ return f[i][j] ;
101
108
}
102
- int res = dfs(i + 1 , k - 1 ) + dfs(i - 1 , k - 1 );
103
- res %= MOD ;
104
- f[i][k] = res;
105
- return res;
109
+ int ans = dfs(i + 1 , j - 1 ) + dfs(Math . abs(i - 1 ), j - 1 );
110
+ ans %= mod;
111
+ return f[i][j] = ans;
106
112
}
107
113
}
108
114
```
@@ -112,23 +118,24 @@ class Solution {
112
118
``` cpp
113
119
class Solution {
114
120
public:
115
- unordered_map<int, int> f;
116
- int mod = 1e9 + 7;
117
- int j;
118
-
119
121
int numberOfWays(int startPos, int endPos, int k) {
120
- j = endPos;
121
- return dfs(startPos, k);
122
- }
123
-
124
- int dfs (int i, int k) {
125
- if (f.count(i * 10000 + k)) return f[ i * 10000 + k] ;
126
- if (abs(i - j) > k) return 0;
127
- if (k == 0) return i == j;
128
- int res = dfs(i - 1, k - 1) + dfs(i + 1, k - 1);
129
- res %= mod;
130
- f[ i * 10000 + k] = res;
131
- return res;
122
+ const int mod = 1e9 + 7;
123
+ int f[ k + 1] [ k + 1 ] ;
124
+ memset(f, -1, sizeof(f));
125
+ function<int(int, int)> dfs = [ &] (int i, int j) -> int {
126
+ if (i > j || j < 0) {
127
+ return 0;
128
+ }
129
+ if (j == 0) {
130
+ return i == 0 ? 1 : 0;
131
+ }
132
+ if (f[ i] [ j ] != -1) {
133
+ return f[ i] [ j ] ;
134
+ }
135
+ f[ i] [ j ] = (dfs(i + 1, j - 1) + dfs(abs(i - 1), j - 1)) % mod;
136
+ return f[ i] [ j ] ;
137
+ };
138
+ return dfs(abs(startPos - endPos), k);
132
139
}
133
140
};
134
141
```
@@ -137,27 +144,32 @@ public:
137
144
138
145
```go
139
146
func numberOfWays(startPos int, endPos int, k int) int {
140
- f := map[int]int{}
141
- var dfs func(i, k int) int
142
- dfs = func(i, k int) int {
143
- if abs(i-endPos) > k {
147
+ const mod = 1e9 + 7
148
+ f := make([][]int, k+1)
149
+ for i := range f {
150
+ f[i] = make([]int, k+1)
151
+ for j := range f[i] {
152
+ f[i][j] = -1
153
+ }
154
+ }
155
+ var dfs func(i, j int) int
156
+ dfs = func(i, j int) int {
157
+ if i > j || j < 0 {
144
158
return 0
145
159
}
146
- if k == 0 {
147
- if i == endPos {
160
+ if j == 0 {
161
+ if i == 0 {
148
162
return 1
149
163
}
150
164
return 0
151
165
}
152
- if v, ok := f[i*10000+k]; ok {
153
- return v
166
+ if f[i][j] != -1 {
167
+ return f[i][j]
154
168
}
155
- res := dfs(i+1, k-1) + dfs(i-1, k-1)
156
- res %= 1e9 + 7
157
- f[i*10000+k] = res
158
- return res
169
+ f[i][j] = (dfs(i+1, j-1) + dfs(abs(i-1), j-1)) % mod
170
+ return f[i][j]
159
171
}
160
- return dfs(startPos, k)
172
+ return dfs(abs( startPos-endPos) , k)
161
173
}
162
174
163
175
func abs(x int) int {
@@ -171,7 +183,25 @@ func abs(x int) int {
171
183
### ** TypeScript**
172
184
173
185
``` ts
174
-
186
+ function numberOfWays(startPos : number , endPos : number , k : number ): number {
187
+ const mod = 10 ** 9 + 7 ;
188
+ const f = new Array (k + 1 ).fill (0 ).map (() => new Array (k + 1 ).fill (- 1 ));
189
+ const dfs = (i : number , j : number ): number => {
190
+ if (i > j || j < 0 ) {
191
+ return 0 ;
192
+ }
193
+ if (j === 0 ) {
194
+ return i === 0 ? 1 : 0 ;
195
+ }
196
+ if (f [i ][j ] !== - 1 ) {
197
+ return f [i ][j ];
198
+ }
199
+ f [i ][j ] = dfs (i + 1 , j - 1 ) + dfs (Math .abs (i - 1 ), j - 1 );
200
+ f [i ][j ] %= mod ;
201
+ return f [i ][j ];
202
+ };
203
+ return dfs (Math .abs (startPos - endPos ), k );
204
+ }
175
205
```
176
206
177
207
### ** ...**
0 commit comments