Valid Parentheses & Longest Valid Parentheses

本文介绍如何使用栈来解决括号有效性验证及寻找最长有效括号子串的问题,并提供两种不同的解决方案:一种利用栈操作,另一种采用动态规划。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Valid Parentheses

Given a string containing just the characters '(', ')''{''}''[' and ']', determine if the input string is valid.

Example

The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not.

分析:

使用stack来保存每个括号,如果最上面的和当前括号匹配,则除去最上面的括号,否则把新括号加入。如果最后stack为空,则所有括号匹配。

 1 public class Solution {
 2     /**
 3      * @param s A string
 4      * @return whether the string is a valid parentheses
 5      */
 6     public boolean isValidParentheses(String s) {
 7         if (s == null || s.length() % 2 == 1) return false;
 8         Stack<Character> stack = new Stack<Character>();
 9         
10         for (int i = 0; i < s.length(); i++) {
11             if (stack.size() == 0) {
12                 stack.push(s.charAt(i));
13             } else {
14                 char c1 = stack.peek();
15                 char c2 = s.charAt(i);
16                 if (c1 == '(' && c2 == ')' || c1 == '[' && c2 == ']' || c1 == '{' && c2 == '}') {
17                     stack.pop();
18                 } else {
19                     stack.push(s.charAt(i));
20                 }
21             }
22         }
23         return stack.isEmpty();
24     }
25 }

 Longest Valid Parentheses

Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.

For "(()", the longest valid parentheses substring is "()", which has length = 2.

Another example is ")()())", where the longest valid parentheses substring is "()()", which has length = 4.

The idea from https://leetcode.com/problems/longest-valid-parentheses/discuss/14126/My-O(n)-solution-using-a-stack

The workflow of the solution is as below.

1. Scan the string from beginning to end. If current character is '(', push its index to the stack. If current character is ')' and the
character at the index of the top of stack is '(', we just find a
matching pair so pop from the stack. Otherwise, we push the index of
')' to the stack.
2. After the scan is done, the stack will only
contain the indices of characters which cannot be matched. Then
 let's use the opposite side - substring between adjacent indices
should be valid parentheses.
3. If the stack is empty, the whole input
string is valid. Otherwise, we can scan the stack to get longest
valid substring as described in step 3.

 1 public class Solution {
 2     public int longestValidParentheses(String s) {
 3         Stack<Integer> st = new Stack<>();
 4         for (int i = 0; i < s.length(); i++) {
 5             if (s.charAt(i) == '(') {
 6                 st.push(i);
 7             } else {
 8                 if (st.empty()) {
 9                     st.push(i);
10                 } else if (s.charAt(st.peek()) == '(') {
11                     st.pop();
12                 } else {
13                     st.push(i);
14                 }
15             }
16         }
17         int longest = 0, end = s.length();
18 
19         while (!st.empty()) {
20             int start = st.pop();
21             longest = Math.max(longest, end - start - 1);
22             end = start;
23         }
24         return Math.max(longest, end);
25     }
26     
27 }

 

Another DP solution (https://leetcode.com/problems/longest-valid-parentheses/discuss/14133/My-DP-O(n)-solution-without-using-stack) is also very good. Here is the idea:

First, create an array longest[], for any longest[i], it stores the longest length of valid parentheses which ends at i.

And the DP idea is :

If s[i] is '(', set longest[i] to 0,because any string end with '(' cannot be a valid one.

Else if s[i] is ')'

     If s[i-1] is '(', longest[i] = longest[i-2] + 2

     Else if s[i-1] is ')' and s[i-longest[i-1]-1] == '(', longest[i] = longest[i-1] + 2 + longest[i-longest[i-1]-2]

For example, input "()(())", at i = 5, longest array is [0,2,0,0,2,0], longest[5] = longest[4] + 2 + longest[1] = 6.

 1 int longestValidParentheses(String s) {
 2     if (s.length() <= 1) {
 3         return 0;
 4     }
 5     int curMax = 0;
 6     int[] longest = new int[s.length()];
 7     for (int i = 1; i < s.length(); i++) {
 8         if (s.charAt(i) == ')') {
 9             if (s.charAt(i - 1) == '(') {
10                 longest[i] = (i - 2) >= 0 ? longest[i - 2] + 2 : 2;
11                 curMax = Math.max(longest[i], curMax);
12             } else {
13                 int indexBeforeMatching = i - longest[i - 1] - 1;
14                 if (indexBeforeMatching >= 0 && s.charAt(indexBeforeMatching) == '(') {
15                     longest[i] = longest[i - 1] + 2 + ((i - longest[i - 1] - 2 >= 0) ? longest[i - longest[i - 1] - 2] : 0);
16                     curMax = Math.max(longest[i], curMax);
17                 }
18             }
19         }
20         // else if s[i] == '(', skip it, because longest[i] must be 0
21     }
22     return curMax;
23 }

 

转载于:https://www.cnblogs.com/beiyeqingteng/p/5666139.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值