@@ -125,6 +125,168 @@ boolean isMatch(String str, String pattern) {
125
125
126
126
如果非要用递归的话,可以按照动态规划那个思路,先压栈,然后出栈过程其实就是动态规划那样了。所以其实不如直接动态规划。
127
127
128
+ # 更新
129
+
130
+ ` 2021.7.7 ` 日更新。(太久没写 ` java ` 代码了,由于换了电脑 ` eclipes ` 也没有,在 ` vscode ` 里写 ` java ` 竟然不会写了,习惯了写 ` js ` ,分号不加,类型不管,写 ` java ` 有点不适应了,哈哈)
131
+
132
+ 上边说到当时按 [ 第 10 题] ( https://leetcode.wang/leetCode-10-Regular-Expression-Matching.html ) 的递归思路超时了,代码如下:
133
+
134
+ ``` java
135
+ class Solution {
136
+ public boolean isMatch (String text , String pattern ) {
137
+ if (pattern. isEmpty())
138
+ return text. isEmpty();
139
+ if (text. isEmpty())
140
+ return pattern. isEmpty() || isStars(pattern);
141
+
142
+ boolean first_match = (! text. isEmpty() && (pattern. charAt(0 ) == text. charAt(0 ) || pattern. charAt(0 ) == ' ?' ));
143
+ if (pattern. charAt(0 ) == ' *' ) {
144
+ return (isMatch(text. substring(1 ), pattern) || (isMatch(text. substring(1 ), pattern. substring(1 ))))
145
+ || (isMatch(text, pattern. substring(1 )));
146
+ } else {
147
+ return first_match && isMatch(text. substring(1 ), pattern. substring(1 ));
148
+ }
149
+ }
150
+
151
+ private boolean isStars (String pattern ) {
152
+ // TODO Auto-generated method stub
153
+ for (int i = 0 ; i < pattern. length(); i++ ) {
154
+ if (pattern. charAt(i) != ' *' ) {
155
+ return false ;
156
+ }
157
+ }
158
+ return true ;
159
+ }
160
+ }
161
+ ```
162
+
163
+ 代码很好理解,这里就不多说了,可以参考 [ 第 10 题] ( https://leetcode.wang/leetCode-10-Regular-Expression-Matching.html ) 的分析,但有个问题就是会超时。
164
+
165
+ ![ ] ( https://windliang.oss-cn-beijing.aliyuncs.com/leetcode44n1.jpg )
166
+
167
+ 前几天 [ @xuyuntian ] ( https://xuyuntian.gitee.io/ ) 加了微信告诉我他写出了一个递归的写法,[ 代码] ( https://gitee.com/xuyuntian/leetcode/blob/master/src/_44.java ) 如下:
168
+
169
+ ``` java
170
+ class Solution {
171
+ public boolean isMatch (String s , String p ) {
172
+ return dfs(new Boolean [s. length()][p. length()], s. toCharArray(), p. toCharArray(), 0 , 0 );
173
+ }
174
+ private boolean dfs (Boolean [][] dp , char [] s , char [] p , int i , int j ) {
175
+ if (i == s. length && j == p. length) return true ;
176
+ if (i > s. length || (i < s. length && j == p. length)) return false ;
177
+ if (i < s. length) {
178
+ if (dp[i][j] != null ) return dp[i][j];
179
+ if (p[j] == ' ?' || p[j] == s[i]) {
180
+ return dp[i][j] = dfs(dp, s, p, i + 1 , j + 1 );
181
+ }
182
+ }
183
+ boolean res = false ;
184
+ if (p[j] == ' *' ) {
185
+ res = dfs(dp, s, p, i + 1 , j + 1 ) || dfs(dp, s, p, i + 1 , j) || dfs(dp, s, p, i, j + 1 );
186
+ }
187
+ if (i < s. length) dp[i][j] = res;
188
+ return res;
189
+ }
190
+ }
191
+ ```
192
+
193
+ 看完以后突然就悟了,对啊,` memoization ` 技术啊,把递归过程中的结果存起来呀!
194
+
195
+ 于是我把自己的递归代码用 ` HashMap ` 改良了一版,把所有结果都用 ` HashMap ` 存起来。
196
+
197
+ ``` java
198
+ class Solution {
199
+ public boolean isMatch (String text , String pattern ) {
200
+ HashMap<String ,Boolean > map= new HashMap<> ();
201
+ return isMatchHelper(text, pattern, map);
202
+ }
203
+ public boolean isMatchHelper (String text , String pattern , HashMap<String ,Boolean > map ) {
204
+ if (pattern. isEmpty())
205
+ return text. isEmpty();
206
+ if (text. isEmpty())
207
+ return pattern. isEmpty() || isStars(pattern);
208
+ String key = text + ' @' + pattern;
209
+ if (map. containsKey(key)) {
210
+ return map. get(key);
211
+ }
212
+ boolean first_match = (! text. isEmpty() && (pattern. charAt(0 ) == text. charAt(0 ) || pattern. charAt(0 ) == ' ?' ));
213
+ if (pattern. charAt(0 ) == ' *' ) {
214
+ boolean res = (isMatchHelper(text. substring(1 ), pattern, map) || (isMatchHelper(text. substring(1 ), pattern. substring(1 ), map)))
215
+ || (isMatchHelper(text, pattern. substring(1 ), map));
216
+ map. put(key, res);
217
+ return res;
218
+ } else {
219
+ boolean res = first_match && isMatchHelper(text. substring(1 ), pattern. substring(1 ), map);
220
+ map. put(key, res);
221
+ return res;
222
+ }
223
+ }
224
+
225
+ private boolean isStars (String pattern ) {
226
+ // TODO Auto-generated method stub
227
+ for (int i = 0 ; i < pattern. length(); i++ ) {
228
+ if (pattern. charAt(i) != ' *' ) {
229
+ return false ;
230
+ }
231
+ }
232
+ return true ;
233
+ }
234
+ }
235
+ ```
236
+
237
+ 遗憾的是竟然超内存了。
238
+
239
+ ![ ] ( https://windliang.oss-cn-beijing.aliyuncs.com/leetcode44n2.jpg )
240
+
241
+ 又看了下 [ @xuyuntian ] ( https://xuyuntian.gitee.io/ ) 的代码,原因只能是 ` HashMap ` 太占内存了,于是我也改成了用数组缓存结果。同样的,需要将下标在递归中传递。
242
+
243
+ ``` java
244
+ class Solution {
245
+ public boolean isMatch (String text , String pattern ) {
246
+ boolean res = isMatchHelper(text, 0 , pattern, 0 , new Boolean [text. length()][pattern. length()]);
247
+ return res;
248
+ }
249
+
250
+ public boolean isMatchHelper (String textOrigin , int textStart , String patternOrigin , int patternStart , Boolean [][] map ) {
251
+ String text = textOrigin. substring(textStart);
252
+ String pattern = patternOrigin. substring(patternStart);
253
+ if (pattern. isEmpty())
254
+ return text. isEmpty();
255
+ if (text. isEmpty())
256
+ return pattern. isEmpty() || isStars(pattern);
257
+ if (map[textStart][patternStart] != null ) {
258
+ return map[textStart][patternStart] ;
259
+ }
260
+ boolean first_match = (! text. isEmpty() && (pattern. charAt(0 ) == text. charAt(0 ) || pattern. charAt(0 ) == ' ?' ));
261
+ if (pattern. charAt(0 ) == ' *' ) {
262
+ boolean res = (isMatchHelper(textOrigin, textStart + 1 ,patternOrigin, patternStart, map) || (isMatchHelper(textOrigin, textStart + 1 ,patternOrigin, patternStart + 1 , map)))
263
+ || (isMatchHelper(textOrigin, textStart, patternOrigin, patternStart + 1 , map));
264
+ map[textStart][patternStart] = res;
265
+ return res;
266
+ } else {
267
+ boolean res = first_match && isMatchHelper(textOrigin, textStart + 1 ,patternOrigin, patternStart + 1 , map);
268
+ map[textStart][patternStart] = res;
269
+ return res;
270
+ }
271
+ }
272
+
273
+ private boolean isStars (String pattern ) {
274
+ // TODO Auto-generated method stub
275
+ for (int i = 0 ; i < pattern. length(); i++ ) {
276
+ if (pattern. charAt(i) != ' *' ) {
277
+ return false ;
278
+ }
279
+ }
280
+ return true ;
281
+ }
282
+ }
283
+ ```
284
+
285
+ 终于 ` AC ` 了!
286
+
287
+ ![ ] ( https://windliang.oss-cn-beijing.aliyuncs.com/leetcode44n3.jpg )
288
+
128
289
# 总
129
290
130
- 动态规划的应用,理清递推的公式就可以。另外迭代的方法,也让人眼前一亮。
291
+ 动态规划的应用,理清递推的公式就可以。另外迭代的方法,也让人眼前一亮。
292
+
0 commit comments