@@ -125,6 +125,168 @@ boolean isMatch(String str, String pattern) {
125125
126126如果非要用递归的话,可以按照动态规划那个思路,先压栈,然后出栈过程其实就是动态规划那样了。所以其实不如直接动态规划。
127127
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+
128289# 总
129290
130- 动态规划的应用,理清递推的公式就可以。另外迭代的方法,也让人眼前一亮。
291+ 动态规划的应用,理清递推的公式就可以。另外迭代的方法,也让人眼前一亮。
292+
0 commit comments