66
66
67
67
<!-- 这里可写通用的实现逻辑 -->
68
68
69
- 动态规划法。
69
+ ** 方法一:动态规划 **
70
70
71
- 假设 ` dp [i]` 表示字符串 s 的前 i 个字符 ` s[1..i] ` 的解码方法数 。
71
+ 我们定义 $f [ i] $ 表示字符串的前 $i$ 个字符的解码方法数,初始时 $f [ 0 ] =1$,其余 $f [ i ] =0$ 。
72
72
73
- 考虑最后一次解码中使用了 s 中的哪些字符:
73
+ 考虑 $f [ i ] $ 如何进行状态转移。
74
74
75
- - 第一种情况是我们使用了一个字符,即 ` s[i] ` 进行解码,那么只要 ` s[i]≠0 ` ,它就可以被解码成 ` A∼I ` 中的某个字母。由于剩余的前 ` i-1 ` 个字符的解码方法数为 ` dp [i-1]` ,所以 ` dp[i] = dp[i -1]` 。
76
- - 第二种情况是我们使用了两个字符,即 ` s[ i-1] ` 和 ` s[i] ` 进行编码。与第一种情况类似, ` s[i-1] ` 不能等于 0,并且 ` s[i-1] ` 和 ` s [i]` 组成的整数必须小于等于 26,这样它们就可以被解码成 ` J∼Z ` 中的某个字母。由于剩余的前 ` i-2 ` 个字符的解码方法数为 ` dp [i-2]` ,所以 ` dp[i] = dp[i-2] ` 。
75
+ - 如果第 $i$ 个字符(即 $ s[ i-1 ] $)单独形成编码,那么它对应一种解码方式,即 $f [ i ] =f [ i-1] $。前提是 $s [ i -1] \neq 0$ 。
76
+ - 如果第 $ i-1$ 个字符和第 $i$ 个字符组成的字符串在 $ [ 1,26 ] $ 范围内,那么它们可以作为一个整体,对应一种解码方式,即 $f [ i ] = f [ i] + f [ i-2 ] $。前提是 $s [ i-2] \neq 0$,且 $s [ i-2] s [ i-1 ] $ 在 $ [ 1,26 ] $ 范围内 。
77
77
78
- 将上面的两种状态转移方程在对应的条件满足时进行累加,即可得到 ` dp[i] ` 的值。在动态规划完成后,最终的答案即为 ` dp[n] ` 。
78
+ 时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 是字符串的长度 。
79
79
80
- 由于 ` dp [i]` 的值仅与 ` dp [i-1]` 和 ` dp [i-2]` 有关,因此可以不定义 dp 数组,可以仅使用三个变量进行状态转移 。
80
+ 我们注意到,状态 $f [ i] $ 仅与状态 $f [ i-1] $ 和状态 $f [ i-2] $ 有关,而与其他状态无关,因此我们可以使用两个变量代替这两个状态,使得原来的空间复杂度 $O(n)$ 降低至 $O(1)$ 。
81
81
82
82
<!-- tabs:start -->
83
83
89
89
class Solution :
90
90
def numDecodings (self , s : str ) -> int :
91
91
n = len (s)
92
- dp = [0 ] * (n + 1 )
93
- dp[0 ] = 1
94
- for i in range (1 , n + 1 ):
95
- if s[i - 1 ] != ' 0' :
96
- dp[i] += dp[i - 1 ]
97
- if i > 1 and s[i - 2 ] != ' 0' and (int (s[i - 2 ]) * 10 + int (s[i - 1 ]) <= 26 ):
98
- dp[i] += dp[i - 2 ]
99
- return dp[n]
92
+ f = [1 ] + [0 ] * n
93
+ for i, c in enumerate (s, 1 ):
94
+ if c != " 0" :
95
+ f[i] = f[i - 1 ]
96
+ if i > 1 and s[i - 2 ] != " 0" and int (s[i - 2 : i]) <= 26 :
97
+ f[i] += f[i - 2 ]
98
+ return f[n]
100
99
```
101
100
102
- 优化空间:
103
-
104
101
``` python
105
102
class Solution :
106
103
def numDecodings (self , s : str ) -> int :
107
- n = len (s)
108
- a, b, c = 0 , 1 , 0
109
- for i in range (1 , n + 1 ):
110
- c = 0
111
- if s[i - 1 ] != ' 0' :
112
- c += b
113
- if i > 1 and s[i - 2 ] != ' 0' and (int (s[i - 2 ]) * 10 + int (s[i - 1 ]) <= 26 ):
114
- c += a
115
- a, b = b, c
116
- return c
104
+ f, g = 0 , 1
105
+ for i, c in enumerate (s, 1 ):
106
+ h = g if c != " 0" else 0
107
+ if i > 1 and s[i - 2 ] != " 0" and int (s[i - 2 : i]) <= 26 :
108
+ h += f
109
+ f, g = g, h
110
+ return g
117
111
```
118
112
119
113
### ** Java**
@@ -124,42 +118,35 @@ class Solution:
124
118
class Solution {
125
119
public int numDecodings (String s ) {
126
120
int n = s. length();
127
- int [] dp = new int [n + 1 ];
128
- dp [0 ] = 1 ;
121
+ int [] f = new int [n + 1 ];
122
+ f [0 ] = 1 ;
129
123
for (int i = 1 ; i <= n; ++ i) {
130
124
if (s. charAt(i - 1 ) != ' 0' ) {
131
- dp [i] += dp [i - 1 ];
125
+ f [i] = f [i - 1 ];
132
126
}
133
- if (i > 1 && s. charAt(i - 2 ) != ' 0'
134
- && ((s. charAt(i - 2 ) - ' 0' ) * 10 + s. charAt(i - 1 ) - ' 0' ) <= 26 ) {
135
- dp[i] += dp[i - 2 ];
127
+ if (i > 1 && s. charAt(i - 2 ) != ' 0' && Integer . valueOf(s. substring(i - 2 , i)) <= 26 ) {
128
+ f[i] += f[i - 2 ];
136
129
}
137
130
}
138
- return dp [n];
131
+ return f [n];
139
132
}
140
133
}
141
134
```
142
135
143
- 优化空间:
144
-
145
136
``` java
146
137
class Solution {
147
138
public int numDecodings (String s ) {
148
139
int n = s. length();
149
- int a = 0 , b = 1 , c = 0 ;
140
+ int f = 0 , g = 1 ;
150
141
for (int i = 1 ; i <= n; ++ i) {
151
- c = 0 ;
152
- if (s. charAt(i - 1 ) != ' 0' ) {
153
- c += b ;
142
+ int h = s . charAt(i - 1 ) != ' 0 ' ? g : 0 ;
143
+ if (i > 1 && s. charAt(i - 2 ) != ' 0' && Integer . valueOf(s . substring(i - 2 , i)) <= 26 ) {
144
+ h += f ;
154
145
}
155
- if (i > 1 && s. charAt(i - 2 ) != ' 0'
156
- && ((s. charAt(i - 2 ) - ' 0' ) * 10 + s. charAt(i - 1 ) - ' 0' ) <= 26 ) {
157
- c += a;
158
- }
159
- a = b;
160
- b = c;
146
+ f = g;
147
+ g = h;
161
148
}
162
- return c ;
149
+ return g ;
163
150
}
164
151
}
165
152
```
@@ -171,19 +158,37 @@ class Solution {
171
158
public:
172
159
int numDecodings(string s) {
173
160
int n = s.size();
174
- vector<int > dp(n + 1);
175
- dp[ 0] = 1;
161
+ int f[ n + 1] ;
162
+ memset(f, 0, sizeof(f));
163
+ f[ 0] = 1;
176
164
for (int i = 1; i <= n; ++i) {
177
165
if (s[ i - 1] != '0') {
178
- dp[ i] += dp[ i - 1] ;
166
+ f[ i] = f[ i - 1] ;
167
+ }
168
+ if (i > 1 && (s[ i - 2] == '1' || s[ i - 2] == '2' && s[ i - 1] <= '6')) {
169
+ f[ i] += f[ i - 2] ;
179
170
}
180
- if (i > 1 && s[ i - 2] != '0') {
181
- if ((s[ i - 2] - '0') * 10 + s[ i - 1] - '0' <= 26) {
182
- dp[ i] += dp[ i - 2] ;
183
- }
171
+ }
172
+ return f[ n] ;
173
+ }
174
+ };
175
+ ```
176
+
177
+ ```cpp
178
+ class Solution {
179
+ public:
180
+ int numDecodings(string s) {
181
+ int n = s.size();
182
+ int f = 0, g = 1;
183
+ for (int i = 1; i <= n; ++i) {
184
+ int h = s[i - 1] != '0' ? g : 0;
185
+ if (i > 1 && (s[i - 2] == '1' || (s[i - 2] == '2' && s[i - 1] <= '6'))) {
186
+ h += f;
184
187
}
188
+ f = g;
189
+ g = h;
185
190
}
186
- return dp [ n ] ;
191
+ return g ;
187
192
}
188
193
};
189
194
```
@@ -193,19 +198,75 @@ public:
193
198
``` go
194
199
func numDecodings (s string ) int {
195
200
n := len (s)
196
- dp := make([]int, n+1)
197
- dp[0] = 1
201
+ f := make ([]int , n+1 )
202
+ f[0 ] = 1
203
+ for i := 1 ; i <= n; i++ {
204
+ if s[i-1 ] != ' 0' {
205
+ f[i] = f[i-1 ]
206
+ }
207
+ if i > 1 && (s[i-2 ] == ' 1' || (s[i-2 ] == ' 2' && s[i-1 ] <= ' 6' )) {
208
+ f[i] += f[i-2 ]
209
+ }
210
+ }
211
+ return f[n]
212
+ }
213
+ ```
214
+
215
+ ``` go
216
+ func numDecodings (s string ) int {
217
+ n := len (s)
218
+ f , g := 0 , 1
198
219
for i := 1 ; i <= n; i++ {
220
+ h := 0
199
221
if s[i-1 ] != ' 0' {
200
- dp[i] += dp[i-1]
222
+ h = g
201
223
}
202
- if i > 1 && s[i-2] != '0' {
203
- if (s[i-2]-'0')*10+(s[i-1]-'0') <= 26 {
204
- dp[i] += dp[i-2]
205
- }
224
+ if i > 1 && (s[i-2 ] == ' 1' || (s[i-2 ] == ' 2' && s[i-1 ] <= ' 6' )) {
225
+ h += f
206
226
}
227
+ f, g = g, h
207
228
}
208
- return dp[n]
229
+ return g
230
+ }
231
+ ```
232
+
233
+ ### ** TypeScript**
234
+
235
+ ``` ts
236
+ function numDecodings(s : string ): number {
237
+ const n = s .length ;
238
+ const f: number [] = new Array (n + 1 ).fill (0 );
239
+ f [0 ] = 1 ;
240
+ for (let i = 1 ; i <= n ; ++ i ) {
241
+ if (s [i - 1 ] !== ' 0' ) {
242
+ f [i ] = f [i - 1 ];
243
+ }
244
+ if (
245
+ i > 1 &&
246
+ (s [i - 2 ] === ' 1' || (s [i - 2 ] === ' 2' && s [i - 1 ] <= ' 6' ))
247
+ ) {
248
+ f [i ] += f [i - 2 ];
249
+ }
250
+ }
251
+ return f [n ];
252
+ }
253
+ ```
254
+
255
+ ``` ts
256
+ function numDecodings(s : string ): number {
257
+ const n = s .length ;
258
+ let [f, g] = [0 , 1 ];
259
+ for (let i = 1 ; i <= n ; ++ i ) {
260
+ let h = s [i - 1 ] !== ' 0' ? g : 0 ;
261
+ if (
262
+ i > 1 &&
263
+ (s [i - 2 ] === ' 1' || (s [i - 2 ] === ' 2' && s [i - 1 ] <= ' 6' ))
264
+ ) {
265
+ h += f ;
266
+ }
267
+ [f , g ] = [g , h ];
268
+ }
269
+ return g ;
209
270
}
210
271
```
211
272
@@ -214,27 +275,36 @@ func numDecodings(s string) int {
214
275
``` cs
215
276
public class Solution {
216
277
public int NumDecodings (string s ) {
217
- if (s .Length == 0 ) return 0 ;
218
-
219
- var f0 = 1 ;
220
- var f1 = 1 ;
221
- var f2 = 1 ;
222
- for (var i = 0 ; i < s .Length ; ++ i )
223
- {
224
- f0 = f1 ;
225
- f1 = f2 ;
226
- f2 = 0 ;
227
- var two = i > 0 ? int .Parse (string .Format (" {0}{1}" , s [i - 1 ], s [i ])) : 0 ;
228
- if (two >= 10 && two <= 26 )
229
- {
230
- f2 += f0 ;
278
+ int n = s .Length ;
279
+ int [] f = new int [n + 1 ];
280
+ f [0 ] = 1 ;
281
+ for (int i = 1 ; i <= n ; ++ i ) {
282
+ if (s [i - 1 ] != '0' ) {
283
+ f [i ] = f [i - 1 ];
284
+ }
285
+ if (i > 1 && (s [i - 2 ] == '1' || (s [i - 2 ] == '2' && s [i - 1 ] <= '6' ))) {
286
+ f [i ] += f [i - 2 ];
231
287
}
232
- if (s [i ] != '0' )
233
- {
234
- f2 += f1 ;
288
+ }
289
+ return f [n ];
290
+ }
291
+ }
292
+ ```
293
+
294
+ ``` cs
295
+ public class Solution {
296
+ public int NumDecodings (string s ) {
297
+ int n = s .Length ;
298
+ int f = 0 , g = 1 ;
299
+ for (int i = 1 ; i <= n ; ++ i ) {
300
+ int h = s [i - 1 ] != '0' ? g : 0 ;
301
+ if (i > 1 && (s [i - 2 ] == '1' || (s [i - 2 ] == '2' && s [i - 1 ] <= '6' ))) {
302
+ h += f ;
235
303
}
304
+ f = g ;
305
+ g = h ;
236
306
}
237
- return f2 ;
307
+ return g ;
238
308
}
239
309
}
240
310
```
0 commit comments