题目
思路
- 动态规划:
- 我们用 dp[i] 表示以 i 结尾的最长有效括号;
- 当 s[i] 为 (,dp[i] 必然等于 0,因为不可能组成有效的括号;那么 s[i] 为 )
- 当 s[i-1] 为 (,那么 dp[i] = dp[i-2] + 2;
- 当 s[i-1] 为 ) 并且 s[i-dp[i-1] - 1] 为 (,那么 dp[i] = dp[i-1] + 2 + dp[i-dp[i-1]-2];
- dp[i-1]表示以i-1结尾的最长有效括号
- dp[i-dp[i-1]-2]表示以i-dp[i-1]-2结尾的最长有效括号
- 比如)()(())为例,设此时i=6
- dp[i-1]表示i为4、5、的括号长度,此时dp[5]=2
- dp[i-dp[i-1]-2]=dp[2]表示i为1、2的括号长度 dp[2]=2
- dp[6] = 2(表示dp[i-1]的括号) + 2(表示新增的两个括号) + 2(表示dp[i-dp[i-1]-2]的括号)
- 本质就是把两个分割有效的括号连在后计算它的长度
- 栈
正逆向扫描
-
代码
//1.动态规划public int longestValidParentheses(String s) {int maxans = 0;int[] dp = new int[s.length()];for (int i = 1; i < s.length(); i++) {if (s.charAt(i) == ')') {if (s.charAt(i - 1) == '(') {dp[i] = (i >= 2 ? dp[i - 2] : 0) + 2;} else if (i - dp[i - 1] > 0 && s.charAt(i - dp[i - 1] - 1) == '(') {dp[i] = dp[i - 1] + ((i - dp[i - 1]) >= 2 ? dp[i - dp[i - 1] - 2] : 0) + 2;}maxans = Math.max(maxans, dp[i]);}}return maxans;}//2.栈public int longestValidParentheses(String s) {int res = 0;Stack<Integer> stack = new Stack<>();stack.push(-1);for (int i = 0; i < s.length(); i++) {if (s.charAt(i) == '(') {stack.push(i);} else {stack.pop();if (stack.isEmpty()) {stack.push(i);} else {res = Math.max(res, i - stack.peek());}}}return res;}//3.正逆向扫描public int longestValidParentheses(String s) {int left = 0, right = 0, maxlength = 0;for (int i = 0; i < s.length(); i++) {if (s.charAt(i) == '(') {left++;} else {right++;}if (left == right) {maxlength = Math.max(maxlength, 2 * right);} else if (right > left) {left = right = 0;}}left = right = 0;for (int i = s.length() - 1; i >= 0; i--) {if (s.charAt(i) == '(') {left++;} else {right++;}if (left == right) {maxlength = Math.max(maxlength, 2 * left);} else if (left > right) {left = right = 0;}}return maxlength;}
-

