zoukankan      html  css  js  c++  java
  • 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.

    这个题很典型的使用stack来解即可。


    想法是存上每个‘(’之前已经匹配的括号数量。
    比如
    ()(()()(()
    第1次遇到前括号,入栈数字是0,然后遇到后括号,现在的长度是2+0
    第2次遇到前括号,入栈数字是2,当前长度重设为0
    第3次遇到前括号,入栈数字是当前长度0.然后后括号,出栈,长度是2+0,
    第4次遇到前括号,入栈数字是当前长度2.然后后括号,出栈,长度是2+2,
    第5次遇到前括号,入栈数字是当前长度4,当前长度重设为0
    第6次遇到前括号,入栈数字是当前长度0,遇到后括号,出栈,长度是2.
    如果栈内仍有数字,目前是2,4,则全部出栈,和当前长度2比。取最长为4.

     1 public class Solution {
     2     public int longestValidParentheses(String s) {
     3         // Start typing your Java solution below
     4         // DO NOT write main() function
     5       Stack<Integer> stack = new Stack<Integer>();
     6       int len = 0;
     7       int maxLen = 0;
     8       for(int i = 0; i < s.length(); ++i) {
     9           if(s.charAt(i) == '(') {
    10               stack.push(len);
    11               len = 0;
    12           } else {
    13               if (stack.empty()) {
    14                   maxLen = Math.max(maxLen, len);
    15                   len = 0;
    16               } else {
    17                   len = len + 2 + stack.pop();
    18               }
    19           }
    20       }
    21       while(!stack.empty()) {
    22           maxLen = Math.max(maxLen, stack.pop());
    23       }
    24       return Math.max(maxLen, len);
    25     }
    26 }

     DP 解法:

    这道题可以用一维动态规划逆向求解。假设输入括号表达式为String s,维护一个长度为s.length的一维数组dp[],数组元素初始化为0。 dp[i]表示从s[i]到s[s.length - 1]最长的有效匹配括号子串长度, 且这个有效匹配括号一定是从i开始的。则存在如下关系:

    • dp[s.length - 1] = 0;
    • 从i - 2 -> 0逆向求dp[],并记录其最大值。若s[i] == '(',则在s中从i开始到s.length - 1计算s[i]的值。这个计算分为两步,通过dp[i + 1]进行的(注意dp[i + 1]已经在上一步求解):
      • 在s中寻找从i + 1开始的有效括号匹配子串长度,即dp[i + 1],跳过这段有效的括号子串,查看下一个字符,其下标为j = i + 1 + dp[i + 1]。若j没有越界,并且s[j] == ‘)’,则s[i ... j]为有效括号匹配,dp[i] =dp[i + 1] + 2
      • 在求得了s[i ... j]的有效匹配长度之后,若j + 1没有越界,则dp[i]的值还要加上从j + 1开始的最长有效匹配,即dp[j + 1]。
     1 public int longestValidParentheses(String s) {
     2         int n = s.length();
     3         int[] dp = new int[n+1];
     4         int max = 0;
     5         for(int i = n-2; i >= 0; i--) {
     6             if(s.charAt(i) == '(') {
     7                 int j = i+1+dp[i+1];
     8                 if(j < n && s.charAt(j) == ')') {
     9                     dp[i] = 2+dp[i+1]+dp[j+1];
    10                     max = Math.max(max, dp[i]);
    11                 }
    12             }
    13         }
    14         
    15         return max;
    16     }

    第二遍:使用和 Largest Rectangle in Histogram 类似的思想做。 这里有一个问题 就是如果都规约到了栈空的时候该如何存, 即 () () 这种情况, 所以这时候使用一个变量base。 再就是如果出现了)  而栈里已经没有( 该怎么办。 这时其实出来base 没有和max比较 其他都已经比较了, 所以将base 和 max 比较,然后清空全部东西。

     1 public class Solution {
     2     public int longestValidParentheses(String s) {
     3         // Start typing your Java solution below
     4         // DO NOT write main() function
     5         if(s == null || s.length() == 0) return 0;
     6         Stack<Integer> st = new Stack<Integer>();// 栈里存的是已匹配的最长长度
     7         int max = 0;
     8         int base = 0;
     9         for(int i = 0; i < s.length(); i ++){
    10             if(s.charAt(i) == '('){
    11                 st.push(0);
    12             }else if(s.charAt(i) == ')' && !st.isEmpty()){//当是)时 进行匹配,消去当前的这一对。并更新最长长度。
    13                 int tmp = st.pop() + 2;
    14                 max = tmp > max ? tmp : max;
    15                 if(!st.isEmpty()){//栈里还有未配对的(
    16                 st.push(tmp + st.pop());
    17                 }else{//栈已经空了,更新base
    18                     base += tmp;
    19                 }
    20             }else{// )多了
    21                 max = base > max ? base : max;
    22                 base = 0;
    23                 st = new Stack<Integer>();
    24             }
    25         }
    26         while(!st.isEmpty()){// 查看栈里剩余的那些最长长度, 这些都是没有配对完的。
    27             int tmp = st.pop();
    28             max = tmp > max ? tmp : max;
    29         }
    30         max = base > max ? base : max;
    31         return max;
    32     }
    33 }

     第三遍:

    先向stack里面放个0 用于都匹配成功的时候存放匹配的个数。

    每当遇到( 时, 放一个0, 说明从这个(开始没有匹配成功一对。

    每当遇到)时, 如果stack 的 size > 0, 说明还有(没用完,那么进行一次匹配 ==> 将其从stack中取出, 并且将结果加到下一层的(中。

                          如果 size ==1 ,说明之前所有的(都用完了, 所以重置stack。

     1 public class Solution {
     2     public int longestValidParentheses(String s) {
     3         if(s == null || s.length() == 0) return 0;
     4         LinkedList<Integer> ll = new LinkedList<Integer>();
     5         ll.push(0); // this is the bot of the stack(nothing in the stack yet)
     6         int max = 0;
     7         for(int i = 0; i < s.length(); i ++){
     8             if(s.charAt(i) == '(') ll.push(0);
     9             else{
    10                 if(ll.size() > 1){
    11                     int count = ll.pop();
    12                     int sum = count + 1 + ll.pop();
    13                     max = max > sum ? max : sum;
    14                     ll.push(sum);
    15                 }else{
    16                     ll.clear();
    17                     ll.push(0);
    18                 }
    19             }
    20         }
    21         return max * 2;
    22     }
    23 }

     第四遍:

     1 public class Solution {
     2     public int longestValidParentheses(String s) {
     3         if(s == null || s.length() == 0) return 0;
     4         LinkedList<Integer> stack = new LinkedList<Integer>();
     5         stack.add(0);
     6         int result = 0;
     7         for(int i = 0; i < s.length(); i ++){
     8             if(s.charAt(i) == '(') stack.push(0);
     9             else{
    10                 if(stack.size() > 1){
    11                     int tmp = stack.pop() + 2;
    12                     result = Math.max(result, tmp);
    13                     tmp += stack.pop();
    14                     stack.push(tmp);
    15                 }else{
    16                     int tmp = stack.pop();
    17                     result = Math.max(result, tmp);
    18                     stack.push(0);
    19                 }
    20             }
    21         }
    22         while(!stack.isEmpty()){
    23             result = Math.max(result, stack.pop());
    24         }
    25         return result;
    26     }
    27 }
  • 相关阅读:
    2,进程----multiprocessing模块介绍
    1,进程----进程理论知识
    对ORM的理解
    对queryset的理解
    个人总结-10-代码测试整合
    个人总结-9-session的使用,十天免登陆
    个人总结-8-重新写注册和登录界面
    个人总结-7- 实现图片在MySQL数据库中的存储,取出以及显示在jsp页面上
    从人机交互看对搜狗输入法的使用感受
    个人总结6-验证码制作总结
  • 原文地址:https://www.cnblogs.com/reynold-lei/p/3366348.html
Copyright © 2011-2022 走看看