Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e0d8b2a

Browse files
WinnoChanazl397985856
WinnoChan
authored andcommitted
azl397985856#32 动态规划: 最长有效括号对长度问题 (azl397985856#20)
1 parent 810af2a commit e0d8b2a

File tree

5 files changed

+89
-5
lines changed

5 files changed

+89
-5
lines changed

‎README.en.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,13 @@ The data structures mainly includes:
184184

185185
#### Hard
186186
- [0023.merge-k-sorted-lists](./problems/23.merge-k-sorted-lists.md)
187+
- [0032.longest-valid-parentheses](./problems/32.longest-valid-parentheses.md) 🆕
187188
- [0042.trapping-rain-water](./problems/42.trapping-rain-water.md)
188-
- [0128.longest-consecutive-sequence](./problems/128.longest-consecutive-sequence.md) 🆕
189+
- [0128.longest-consecutive-sequence](./problems/128.longest-consecutive-sequence.md) 🆕
189190
- [0145.binary-tree-postorder-traversal](./problems/145.binary-tree-postorder-traversal.md)
190191
- [0146.lru-cache](./problems/146.lru-cache.md)
191192
- [0239.sliding-window-maximum](./problems/239.sliding-window-maximum.md)
192-
- [0295.find-median-from-data-stream](./problems/295.find-median-from-data-stream.md) 🆕
193+
- [0295.find-median-from-data-stream](./problems/295.find-median-from-data-stream.md) 🆕
193194
- [0301.remove-invalid-parentheses](./problems/301.remove-invalid-parentheses.md)
194195

195196

‎README.md‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,13 @@ leetcode 题解,记录自己的 leetcode 解题之路。
182182

183183
#### 困难难度
184184
- [0023.merge-k-sorted-lists](./problems/23.merge-k-sorted-lists.md)
185+
- [0032.longest-valid-parentheses](./problems/32.longest-valid-parentheses.md) 🆕
185186
- [0042.trapping-rain-water](./problems/42.trapping-rain-water.md)
186-
- [0128.longest-consecutive-sequence](./problems/128.longest-consecutive-sequence.md) 🆕
187+
- [0128.longest-consecutive-sequence](./problems/128.longest-consecutive-sequence.md) 🆕
187188
- [0145.binary-tree-postorder-traversal](./problems/145.binary-tree-postorder-traversal.md)
188189
- [0146.lru-cache](./problems/146.lru-cache.md)
189190
- [0239.sliding-window-maximum](./problems/239.sliding-window-maximum.md)
190-
- [0295.find-median-from-data-stream](./problems/295.find-median-from-data-stream.md) 🆕
191+
- [0295.find-median-from-data-stream](./problems/295.find-median-from-data-stream.md) 🆕
191192
- [0301.remove-invalid-parentheses](./problems/301.remove-invalid-parentheses.md)
192193

193194
### 数据结构与算法的总结
@@ -253,4 +254,4 @@ http://t.me/leetcode_intl
253254

254255
- 如果有想法和创意,请提[issue](https://github.com/azl397985856/leetcode/issues)或者进群提
255256
- 如果想贡献代码,请提[PR](https://github.com/azl397985856/leetcode/pulls)
256-
- 如果需要修改项目中图片,[这里](./assets/drawio/)存放了项目中绘制图的源代码, 大家可以用[draw.io](https://www.draw.io/)打开进行编辑。
257+
- 如果需要修改项目中图片,[这里](./assets/drawio/)存放了项目中绘制图的源代码, 大家可以用[draw.io](https://www.draw.io/)打开进行编辑。
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<mxfile modified="2019年06月04日T13:25:22.060Z" host="www.draw.io" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36" etag="8H9UqhbsuCS1_Zfojrgc" version="10.7.4" type="device"><diagram id="oSH-UZAoREgWgg9KTufO" name="Page-1">7Z1db6M4FIZ/jTU7F13xHXOZr3alnVlp1YuZnTua0CSzacgQOm33168NNhBMUjqNOTYgVSoYMI4fH9vv4RiQPX14vomD/fpztAy3yDKWz8ieIcsyTReTfzTlJUtxPS9LWMWbJTupSLjd/BeyRIOlPm6W4eHoxCSKtslmf5y4iHa7cJEcpQVxHD0dn3YfbY/vug9WoZBwuwi2YuqXzTJZZ6nYNYr0P8LNas3vbBrsyEPAT2YJh3WwjJ5KSfYc2dM4ipJs6+F5Gm5p5fF6ya67PnE0L1gc7pImF6yC73fO/ttff45//P0UWMZ8/eBfsVx+BttH9oOR5W1JfpP7iGRLSp28sKrwfjxG/MDVIQU1JidYzv65OEi2VvT/bzwbUp4spyydVUWeqRVHj7tlSItokMNP600S3u6DBT36RFoUSVsnD1uyZ+ZXl38yL38YJ+FzKYlVwU0YPYRJ/EJOYUctzoe1R8x2nwq4Dktal7jytIA1p1WecVHjZINV+hsAWJIAfFQWgKMWALt3ALBaAJy+dUG2pRYAr28ATE8tAKO+dUGOYoMw7hsAWzELMGVNgwxVCVTnoXmfBIZA1kRIXQSOaghkTYXURYBVQ+D2DUF1NgqPQNZ0SA6C+812O422UZxea9/fh95iQdIPSRz9G5aOLEf+nWHImcHCQ5M1hVLWbqpzWHgEft8QVGex4Ah4V6oJApiuS7XxxpLlA+8QtKpayWmAQZMlGK0OQXNUg9Y/iYlVQ9A7iVnVN/AIZPnbOzTeVPUNPDS9ROkFEFT1DTyC3knMqr6BR6CXxFRC34BDswdR+vo8rdLZ5ZMGMGiyRGmH9Q08NFmi1OkQNKwaNL1EKQi0qoaCh6bXYzolNBQ8NL2E7wUQVDUUPILeydiqhoJHoJeMVUJDwUMbhO/rM7tqZwf9YI9nPGioN2gocGiyhG+XNRQ4NFnCt0Pdo6ChwKHp9ShQDQ0FDk0v4XsBBIKGAkcgS8Z63bEbQXWBQ9NL+KqhusCh6SWVLzGzqwYVQwtfRy/hewkE1VVB0Aj4qyZ6hKC6KggcgV4hwpcYwKtR2uAI9HpMd4nhuLq6ARyBXoLxAgiENT7gCHon/4Q1PuAI9HqKqYSSgIc2yL/XZ13VgF8DGlr/5F91xQ44gv7Jv+qKHWgEfPzrDwJhxQ44AksrBEo8KYGH1jvBKKzYAUfQO8EorNgBR6CXYFRCrcBDGyTm6/O0amcH/Qo7T5bEtDoErapvwKHJkpgdjjaDh9Y7USooImgEI70eiKmhiMCh6SVjL4BAUETgCHonSgVFBI5AL1GqhiKChubrZTdKKCIHWsb6siytw4oIHposh1GHFRE8tMFh9PpExFINml6Pt5XQUPDQ9PI9gECrqi5waPk3+YYlO82FmgLUBifT6x2kaqOayT/lU6rGcLkKb9luFCfraBXtgu28SJ0cV3Rxzqco2rPq/R4myQv7PmjwmETHlR8+b5Kvpe1/aFa/u2xv9sxyTnde+M6O/OCv5Z3SVXS3uCzd49edxHaIHuNFeLZJs8pJgngVJmfOZBM6WnNnm0EcboNk8zM8KocEU5TlOjyo6req6DJoB4jJP880mFVd87QbmpWrml3J8mst9zyfu7iwKS1MDTxY3OTf4Rpsra7JOg1tjWNUxtZkuSN1tjXoJd4m/+DaYGt1TdZtOl10FbM1WV5kjW0NPKzQNL3B1k43Wa/puOYrZmuynP862xr0S/dN/hXLwdbqmuyooa3xYA1lbE1WkK/OtgbvG8GDrZ1usrihrfEXEytja7Kej2psa+AvQjb5V2YHW6trsn5DW+Ovo1PG1mQ91tbZ1sB9I9zYB1ur64iMhraWP0dWxdh4yQdjQyDPrV+m4VNw5bx8cW4+zb8d/NkcJ1dirMEmrQuLZGeguYswRv6MboxHCE/SlCnyPVLn7mSDXHLIQROMJuP8GozGJhpjNB+hMTk2Tjf8dIPkMkP+KE2ZorHHL7Zoij9G2EFzD/lTRObWcx/5Lppc8xQ/3UgLRDZIUUgOtDTXaDJKcyYbfukql96xuMXYqGskJ1uD2U5raPLGP9xme7Bq24OZsT1Q5qTJlKh/+O0D5+4hUseTFBOeofE8r++8uglkgpGeQuDMETatkpkWp+X5vQF7Whw8Y4dIImmG2EaTrKTkKpeWlBSAbPt2WgCDliG/F7kRbXTs5NrmrX7zqRu6W20+p5/rHvbB7te7eLPUULKcJIQuLYMQ39eGLnkLHN7dXwaauF4BdgTQerVCS8iEURsWmaynTHaHkAlrFWCRyXpY0cryknaQiSsVYJGd9sO9bywzujOWiesUYJHJcue0Eu/eDjJxlQIsMmleAbc7zMQ1CrDM+Aefu+ugow2GFcT0mjrs6ts3O7Hsrzs33LTvrTtb7JNmeexma2qqplUfDU+FuYPGVirMp1TvnzJebR19wCbb+Tj6C5qs1dBk4UJ9z5b70jZrnnC6d99ooa3WPK30NfCnhebSDUd1kyPfG9nBWSN9hwYBhyZL67fiUWsHmuAEBYcmK8KtFZ9aS9CU6x61fo1lS9CqjlBwaLKcNKPuQBOcNNDQ+ExXT2doSxORqv8aHJqsF0m04g5tB5rgWgOH9pqIU9of2hI05Syt5iE6jSm5pn9zTOORJgYLJRnPsqCTTR5akklpFv4kamoeicUiXdK4Jt/JL6lznvGcabAOuz6LuJryu45PRWP5yL8WY7hKkT8XDoNJ3Tbs2ny/iRvn18Nk6hZutBtkJcp6GmVlFax9A+FpEXnlBQ+02nZ3B/qvFOSUxlH5o+NwpQyhRnFLtUtE2yUianZa+/bpuLeP74l7K4tCIe7N5wGQmNokNku279EN3ymXh7QVi7SVLMm6ylpCdsydlcI4Z4hI0XR4oKda1WvN47PJXcy02PO04/KQj9P25iPssjA7ViTecaXNtNrQWPyoX7RPe1YuoTWxmkfgWe+ocOdtFZ4GGpKulG7MSWHORa6mmRSlpUPTJG1BLPGqOHauitOfTWuW1bWlg93Wjbvt2q3otqF26wx2O9jtYLcn7RZ+BiR67qjdun2dAdUucGyXiOiWo7XvdbUndavXOkNPCtuTZik4/7WeDnYLv+JC9MxSux31tSetXVHXLpEat2uxqi1dgUS6hLIZlGr/3evfckfSyYVwOthVrUfvQhTJbhxR12h+7Ib8pPXnaBnSM/4H</diagram></mxfile>
116 KB
Loading[フレーム]
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
## 题目地址
2+
https://leetcode.com/problems/longest-valid-parentheses/
3+
4+
## 题目描述
5+
6+
```
7+
Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.
8+
9+
Example 1:
10+
11+
Input: "(()"
12+
Output: 2
13+
Explanation: The longest valid parentheses substring is "()"
14+
Example 2:
15+
16+
Input: ")()())"
17+
Output: 4
18+
Explanation: The longest valid parentheses substring is "()()"
19+
```
20+
21+
## 思路(动态规划)
22+
23+
所有的动态规划问题, 首先需要解决的就是如何寻找合适的子问题.
24+
该题需要我们找到最长的有效括号对, 我们首先想到的就是定义**dp[i]为前i个字符串的最长有效括号对长度**, 但是随后我们会发现, 这样的定义, 我们无法找到dp[i]和dp[i-1]的任何关系.
25+
所以, 我们需要重新找一个新的定义: 定义**dp[i]为以第i个字符结尾的最长有效括号对长度**. 然后, 我们通过下面这个例子找一下dp[i]和dp[i-1]之间的关系.
26+
27+
```python
28+
s = '(())())'
29+
```
30+
31+
从上面的例子我们可以观察出一下几点结论(**描述中i为图中的dp数组的下标, 对应s的下标应为i-1, 第i个字符的i从1开始**).
32+
1. base case: 空字符串的最长有效括号对长度肯定为0, 即: dp[0] = 0;
33+
2. s的第**1**个字符结尾的最长有效括号对长度为0, s的第**2**个字符结尾的最长有效括号对长度也为0, 这个时候我们可以得出结论: 最长有效括号对不可能以'('结尾, 即: dp[1] = d[2] = 0;
34+
3. 当i等于3时, 我们可以看出dp[2]=0, dp[3]=2, 因为第2个字符(**s[1]**)和第3个字符(**s[2]**)是配对的;
35+
当i等于4时, 我们可以看出dp[3]=2, dp[4]=4, 因为我们配对的是第1个字符(**s[0]**)和第4个字符(**s[3]**);
36+
因此, 我们可以得出结论: 如果第**i**个字符和第<strong>i-1-dp[i-1]</strong>个字符是配对的, 则dp[i] = dp[i-1] + 2, 其中: i-1-dp[i-1] >= 1, 因为第0个字符没有任何意义;
37+
4. 根据第3条规则来计算的话, 我们发现dp[5]=0, dp[6]=2, 但是显然, dp[6]应该为6才对, 但是我们发现可以将"(())"和"()"进行拼接, 即: dp[i] += dp[i-dp[i]], 即: dp[6] = 2 + dp[6-2] = 2 + dp[4] = 6
38+
39+
根据以上规则, 我们求解dp数组的结果为: [0, 0, 0, 2, 4, 0, 6, 0], 其中最长有效括号对的长度为6. 以下为图解:
40+
![32.longest-valid-parentheses](../assets/problems/32.longest-valid-parentheses.png)
41+
42+
## 关键点解析
43+
44+
1. 第3点特征, 需要检查的字符是s[i-1]和s[i-2-dp[i-1]], 根据定义可知: i-1 >= dp[i-1], 但是i-2不一定大于dp[i-1], 因此, 需要检查越界;
45+
3. 第4点特征最容易遗漏, 还有就是不需要检查越界, 因为根据定义可知: i >= dp[i], 所以dp[i-dp[i]]的边界情况是dp[0];
46+
47+
## 代码
48+
49+
* 语言支持: Python
50+
51+
Python Code:
52+
```
53+
class Solution:
54+
def longestValidParentheses(self, s: str) -> int:
55+
mlen = 0
56+
slen = len(s)
57+
dp = [0] * (slen + 1)
58+
for i in range(1, len(s) + 1):
59+
# 有效的括号对不可能会以'('结尾的
60+
if s[i - 1] == '(':
61+
continue
62+
63+
left_paren = i - 2 - dp[i - 1]
64+
if left_paren >= 0 and s[left_paren] == '(':
65+
dp[i] = dp[i - 1] + 2
66+
67+
# 拼接有效括号对
68+
if dp[i - dp[i]]:
69+
dp[i] += dp[i - dp[i]]
70+
71+
# 更新最大有效扩对长度
72+
if dp[i] > mlen:
73+
mlen = dp[i]
74+
75+
return mlen
76+
```
77+
78+
## 扩展
79+
80+
1. 如果判断的不仅仅只有'('和')', 还有'[', ']', '{'和'}', 该怎么办?
81+
2. 如果输出的不是长度, 而是任意一个最长有效括号对的字符串, 该怎么办?

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /