@@ -78,15 +78,21 @@ tags:
78
78
79
79
### 方法一:记忆化搜索
80
80
81
- 设计函数 ` dfs(i, cnt) ` 表示从下标 ` i ` 开始,且当前已经分配了 ` cnt ` 个座位的方案数 。
81
+ 我们设计一个函数 $\textit{ dfs} (i, k)$,表示在走廊的第 $i$ 个位置,已经放置了 $k$ 个屏风的情况下,划分走廊的方案数。那么答案就是 $\textit{dfs}(0, 0)$ 。
82
82
83
- 对于下标 ` i ` 处的字符,如果是 ` S ` ,那么 ` cnt ` 加 ` 1 ` ,如果此时 ` cnt ` 超过 ` 2 ` ,那么直接返回 ` 0 ` 。
83
+ 函数 $\textit{dfs}(i, k)$ 的计算过程如下:
84
84
85
- 否则我们可以选择不放置屏风,此时的方案数为 ` dfs(i + 1, cnt) ` ;如果此时 ` cnt ` 为 ` 2 ` ,我们还可以选择放置屏风,此时的方案数为 ` dfs(i + 1, 0) ` 。
85
+ 如果 $i \geq \textit{len}(\textit{corridor})$,表示已经遍历完了走廊,此时如果 $k = 2$,说明找到了一种划分走廊的方案,返回 $1$,否则返回 $0$;
86
86
87
- 最终返回方案数,记忆化搜索即可。
87
+ 否则,我们需要考虑当前位置 $i$ 的情况:
88
88
89
- 时间复杂度 $O(n\times 3)$,空间复杂度 $O(n\times 3)$。其中 $n$ 为字符串 ` corridor ` 的长度。
89
+ - 如果 $\textit{corridor}[ i] = \text{'S'}$,表示当前位置是一个座位,我们将 $k$ 加 $1$;
90
+ - 如果 $k > 2$,表示当前位置放置的屏风数量超过了 $2$,返回 $0$;
91
+ - 否则,我们可以选择不放置屏风,即 $\textit{dfs}(i + 1, k)$;如果 $k = 2$,我们还可以选择放置屏风,即 $\textit{dfs}(i + 1, 0)$;我们将这两种情况的结果相加并取模 $10^9 + 7$,即 $\textit{ans} = (\textit{ans} + \textit{dfs}(i + 1, k)) \bmod \text{mod}$。
92
+
93
+ 最后,我们返回 $\textit{dfs}(0, 0)$。
94
+
95
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是走廊的长度。
90
96
91
97
<!-- tabs:start -->
92
98
@@ -96,19 +102,17 @@ tags:
96
102
class Solution :
97
103
def numberOfWays (self , corridor : str ) -> int :
98
104
@cache
99
- def dfs (i , cnt ) :
100
- if i == n :
101
- return int (cnt == 2 )
102
- cnt += corridor[i] == ' S '
103
- if cnt > 2 :
105
+ def dfs (i : int , k : int ) -> int :
106
+ if i >= len (corridor) :
107
+ return int (k == 2 )
108
+ k += int ( corridor[i] == " S " )
109
+ if k > 2 :
104
110
return 0
105
- ans = dfs(i + 1 , cnt)
106
- if cnt == 2 :
107
- ans += dfs(i + 1 , 0 )
108
- ans %= mod
111
+ ans = dfs(i + 1 , k)
112
+ if k == 2 :
113
+ ans = (ans + dfs(i + 1 , 0 )) % mod
109
114
return ans
110
115
111
- n = len (corridor)
112
116
mod = 10 ** 9 + 7
113
117
ans = dfs(0 , 0 )
114
118
dfs.cache_clear()
@@ -119,39 +123,34 @@ class Solution:
119
123
120
124
``` java
121
125
class Solution {
122
- private String s;
123
126
private int n;
124
- private int [][] f;
125
- private static final int MOD = (int ) 1e9 + 7 ;
127
+ private char [] s;
128
+ private Integer [][] f;
129
+ private final int mod = (int ) 1e9 + 7 ;
126
130
127
131
public int numberOfWays (String corridor ) {
128
- s = corridor;
129
- n = s. length();
130
- f = new int [n][3 ];
131
- for (var e : f) {
132
- Arrays . fill(e, - 1 );
133
- }
132
+ s = corridor. toCharArray();
133
+ n = s. length;
134
+ f = new Integer [n][3 ];
134
135
return dfs(0 , 0 );
135
136
}
136
137
137
- private int dfs (int i , int cnt ) {
138
- if (i = = n) {
139
- return cnt == 2 ? 1 : 0 ;
138
+ private int dfs (int i , int k ) {
139
+ if (i > = n) {
140
+ return k == 2 ? 1 : 0 ;
140
141
}
141
- cnt += s. charAt(i) == ' S' ? 1 : 0 ;
142
- if (cnt > 2 ) {
143
- return 0 ;
142
+ if (f[i][k] != null ) {
143
+ return f[i][k];
144
144
}
145
- if (f[i][cnt] != - 1 ) {
146
- return f[i][cnt];
145
+ k += s[i] == ' S' ? 1 : 0 ;
146
+ if (k > 2 ) {
147
+ return 0 ;
147
148
}
148
- int ans = dfs(i + 1 , cnt);
149
- if (cnt == 2 ) {
150
- ans += dfs(i + 1 , 0 );
151
- ans %= MOD ;
149
+ int ans = dfs(i + 1 , k);
150
+ if (k == 2 ) {
151
+ ans = (ans + dfs(i + 1 , 0 )) % mod;
152
152
}
153
- f[i][cnt] = ans;
154
- return ans;
153
+ return f[i][k] = ans;
155
154
}
156
155
}
157
156
```
@@ -161,26 +160,29 @@ class Solution {
161
160
``` cpp
162
161
class Solution {
163
162
public:
164
- const int mod = 1e9 + 7;
165
-
166
163
int numberOfWays(string corridor) {
167
164
int n = corridor.size();
168
- vector<vector<int>> f(n, vector<int>(3, -1));
169
- function<int(int, int)> dfs;
170
- dfs = [&](int i, int cnt) {
171
- if (i == n) return cnt == 2 ? 1 : 0;
172
- cnt += corridor[i] == 'S';
173
- if (cnt > 2) return 0;
174
- if (f[i][cnt] != -1) return f[i][cnt];
175
- int ans = dfs(i + 1, cnt);
176
- if (cnt == 2) {
177
- ans += dfs(i + 1, 0);
178
- ans %= mod;
165
+ int f[ n] [ 3 ] ;
166
+ memset(f, -1, sizeof(f));
167
+ const int mod = 1e9 + 7;
168
+ auto dfs = [ &] (auto&& dfs, int i, int k) -> int {
169
+ if (i >= n) {
170
+ return k == 2;
179
171
}
180
- f[i][cnt] = ans;
181
- return ans;
172
+ if (f[ i] [ k ] != -1) {
173
+ return f[ i] [ k ] ;
174
+ }
175
+ k += corridor[ i] == 'S';
176
+ if (k > 2) {
177
+ return 0;
178
+ }
179
+ f[ i] [ k ] = dfs(dfs, i + 1, k);
180
+ if (k == 2) {
181
+ f[ i] [ k ] = (f[ i] [ k ] + dfs(dfs, i + 1, 0)) % mod;
182
+ }
183
+ return f[ i] [ k ] ;
182
184
};
183
- return dfs(0 , 0 );
185
+ return dfs(dfs, 0, 0);
184
186
}
185
187
};
186
188
```
@@ -190,38 +192,33 @@ public:
190
192
```go
191
193
func numberOfWays(corridor string) int {
192
194
n := len(corridor)
193
- var mod int = 1e9 + 7
194
- f := make ([][]int , n)
195
+ f := make([][3]int, n)
195
196
for i := range f {
196
- f[i] = make ([]int , 3 )
197
- for j := range f[i] {
198
- f[i][j] = -1
199
- }
197
+ f[i] = [3]int{-1, -1, -1}
200
198
}
201
- var dfs func (i, cnt int ) int
202
- dfs = func (i, cnt int ) int {
203
- if i == n {
204
- if cnt == 2 {
199
+ const mod = 1e9 + 7
200
+ var dfs func(int, int) int
201
+ dfs = func(i, k int) int {
202
+ if i >= n {
203
+ if k == 2 {
205
204
return 1
206
205
}
207
206
return 0
208
207
}
208
+ if f[i][k] != -1 {
209
+ return f[i][k]
210
+ }
209
211
if corridor[i] == 'S' {
210
- cnt ++
212
+ k ++
211
213
}
212
- if cnt > 2 {
214
+ if k > 2 {
213
215
return 0
214
216
}
215
- if f[i][cnt] != -1 {
216
- return f[i][cnt]
217
- }
218
- ans := dfs (i+1 , cnt)
219
- if cnt == 2 {
220
- ans += dfs (i+1 , 0 )
221
- ans %= mod
217
+ f[i][k] = dfs(i+1, k)
218
+ if k == 2 {
219
+ f[i][k] = (f[i][k] + dfs(i+1, 0)) % mod
222
220
}
223
- f[i][cnt] = ans
224
- return ans
221
+ return f[i][k]
225
222
}
226
223
return dfs(0, 0)
227
224
}
@@ -231,26 +228,148 @@ func numberOfWays(corridor string) int {
231
228
232
229
``` ts
233
230
function numberOfWays(corridor : string ): number {
234
- const M: number = 1e9 + 7 ;
235
- const seatNumbers: number [] = [];
231
+ const n = corridor .length ;
232
+ const mod = 10 ** 9 + 7 ;
233
+ const f: number [][] = Array .from ({ length: n }, () => Array (3 ).fill (- 1 ));
234
+ const dfs = (i : number , k : number ): number => {
235
+ if (i >= n ) {
236
+ return k === 2 ? 1 : 0 ;
237
+ }
238
+ if (f [i ][k ] !== - 1 ) {
239
+ return f [i ][k ];
240
+ }
241
+ if (corridor [i ] === ' S' ) {
242
+ ++ k ;
243
+ }
244
+ if (k > 2 ) {
245
+ return (f [i ][k ] = 0 );
246
+ }
247
+ f [i ][k ] = dfs (i + 1 , k );
248
+ if (k === 2 ) {
249
+ f [i ][k ] = (f [i ][k ] + dfs (i + 1 , 0 )) % mod ;
250
+ }
251
+ return f [i ][k ];
252
+ };
253
+ return dfs (0 , 0 );
254
+ }
255
+ ```
256
+
257
+ <!-- tabs: end -->
258
+
259
+ <!-- solution: end -->
260
+
261
+ <!-- solution: start -->
262
+
263
+ ### 方法二:数学
264
+
265
+ 我们可以将每两个座位划分为一组。在相邻的两组座位之间,如果前一组的最后一个座位和后一组的第一个座位之间的距离为 $x$,那么就有 $x$ 种放置屏风的方案。
266
+
267
+ 我们遍历走廊,用一个变量 $\textit{cnt}$ 记录当前座位数,用一个变量 $\textit{last}$ 记录上一个座位的位置。
236
268
237
- for (let i = 0 ; i < corridor .length ; i ++ ) {
238
- if (corridor .charAt (i ) === ' S' ) {
239
- seatNumbers .push (i );
269
+ 当遍历到一个座位时,我们将 $\textit{cnt}$ 加 $1$,如果 $\textit{cnt}$ 大于 $2$ 且 $\textit{cnt}$ 为奇数,那么我们就需要在 $\textit{last}$ 和当前座位之间放置一个屏风,此时的方案数就是 $\textit{ans} \times (i - \textit{last})$,其中 $\textit{ans}$ 是之前的方案数。然后,我们更新 $\textit{last}$ 为当前座位的位置 $i$。
270
+
271
+ 最后,如果 $\textit{cnt}$ 大于 $0$ 且 $\textit{cnt}$ 为偶数,那么返回 $\textit{ans}$,否则返回 $0$。
272
+
273
+ 时间复杂度 $O(n)$,其中 $n$ 是走廊的长度。空间复杂度 $O(1)$。
274
+
275
+ <!-- tabs: start -->
276
+
277
+ #### Python3
278
+
279
+ ``` python
280
+ class Solution :
281
+ def numberOfWays (self , corridor : str ) -> int :
282
+ mod = 10 ** 9 + 7
283
+ ans, cnt, last = 1 , 0 , 0
284
+ for i, c in enumerate (corridor):
285
+ if c == " S" :
286
+ cnt += 1
287
+ if cnt > 2 and cnt % 2 :
288
+ ans = ans * (i - last) % mod
289
+ last = i
290
+ return ans if cnt and cnt % 2 == 0 else 0
291
+ ```
292
+
293
+ #### Java
294
+
295
+ ``` java
296
+ class Solution {
297
+ public int numberOfWays (String corridor ) {
298
+ final int mod = (int ) 1e9 + 7 ;
299
+ long ans = 1 , cnt = 0 , last = 0 ;
300
+ for (int i = 0 ; i < corridor. length(); ++ i) {
301
+ if (corridor. charAt(i) == ' S' ) {
302
+ if (++ cnt > 2 && cnt % 2 == 1 ) {
303
+ ans = ans * (i - last) % mod;
304
+ }
305
+ last = i;
306
+ }
240
307
}
308
+ return cnt > 0 && cnt % 2 == 0 ? (int ) ans : 0 ;
241
309
}
310
+ }
311
+ ```
312
+
313
+ #### C++
242
314
243
- if (seatNumbers .length % 2 !== 0 || seatNumbers .length === 0 ) {
244
- return 0 ;
315
+ ``` cpp
316
+ class Solution {
317
+ public:
318
+ int numberOfWays(string corridor) {
319
+ const int mod = 1e9 + 7;
320
+ long long ans = 1;
321
+ int cnt = 0, last = 0;
322
+ for (int i = 0; i < corridor.length(); ++i) {
323
+ if (corridor[ i] == 'S') {
324
+ if (++cnt > 2 && cnt % 2) {
325
+ ans = ans * (i - last) % mod;
326
+ }
327
+ last = i;
328
+ }
329
+ }
330
+ return cnt > 0 && cnt % 2 == 0 ? ans : 0;
245
331
}
332
+ };
333
+ ```
246
334
247
- let result : number = 1 ;
335
+ #### Go
248
336
249
- for (let i = 2 ; i < seatNumbers .length ; i += 2 ) {
250
- result = (result * (seatNumbers [i ] - seatNumbers [i - 1 ])) % M ;
251
- }
337
+ ```go
338
+ func numberOfWays(corridor string) int {
339
+ const mod int = 1e9 + 7
340
+ ans, cnt, last := 1, 0, 0
341
+ for i, c := range corridor {
342
+ if c == 'S' {
343
+ cnt++
344
+ if cnt > 2 && cnt%2 == 1 {
345
+ ans = ans * (i - last) % mod
346
+ }
347
+ last = i
348
+ }
349
+ }
350
+ if cnt > 0 && cnt%2 == 0 {
351
+ return ans
352
+ }
353
+ return 0
354
+ }
355
+ ```
356
+
357
+ #### TypeScript
252
358
253
- return result ;
359
+ ``` ts
360
+ function numberOfWays(corridor : string ): number {
361
+ const mod = 10 ** 9 + 7 ;
362
+ const n = corridor .length ;
363
+ let [ans, cnt, last] = [1 , 0 , 0 ];
364
+ for (let i = 0 ; i < n ; ++ i ) {
365
+ if (corridor [i ] === ' S' ) {
366
+ if (++ cnt > 2 && cnt % 2 ) {
367
+ ans = (ans * (i - last )) % mod ;
368
+ }
369
+ last = i ;
370
+ }
371
+ }
372
+ return cnt > 0 && cnt % 2 === 0 ? ans : 0 ;
254
373
}
255
374
```
256
375
0 commit comments