zoukankan      html  css  js  c++  java
  • 最长有效括号(leetcode32)

    给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

    示例:

    输入:s = ")()())"
    输出:4
    解释:最长有效括号子串是 "()()"

    解析:

    方法一:动态规则

    我们定义dp[i] 表示以下标 i 结尾的最长有效括号的长度。

    将dp数组全初始化为0.

    显然,有效的子串一定以 ) 结尾,因此我们可以知道以  ( 对应的dp一定为0。

    我们只需要求 ) 在dp数组中对应位置的值。

    我们从前往后遍历字符串求解dp值,我们每两个字符检查一次:

    1. s [ i ] = ')' 且 s[ i-1 ] = '(' ,也就是形如 “...()”, 可推断出: dp [ i ] = dp[ i-2 ] + 2 

      我们可以理解,因为结束部分的  () 是一个有效字符串,并且将之前的有效字符串的长度增加了 2 。

    2.  s [ i ] = ')' 且 s[ i-1 ] = ')' , 即形如 “...))” , 可以推断出:

    如果 s [ i-dp[i-1] -1 ] = '(' , 那么 dp[ i ] = dp[ i-1 ]  + dp[ i - dp[i-1] - 2] + 2

      我们可以理解,dp[i-1] 表示 i-1 位置的有效长度, i - dp[i-1] -1 表示跟 i 减去有效长度后前一个位置的字符与 i 相比是否是有效的,即是否为 ( 。

    如果是,则表示 i 位置也有效,则 i 位置的有效长度 为 i-1位置的有效长度(dp[i-1]) + 2,然后再加上,这些有效位置的前一个位置的有效长度,

    即 dp [ i-dp[ i-1 ] -2 ] 。

    如下图

    代码如下:

    public class leetcode32 {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
    
            String s = ")()())";
            System.out.println(longestValidParentheses(s));
        }
    
        //动态规划
        public static 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;
        }
    }

    方法二:栈

    具体做法是我们始终保持栈底元素为当前已经遍历过的元素中「最后一个没有被匹配的右括号的下标」,这样的做法主要是考虑了边界条件的处理,栈里其他元素维护左括号的下标:

    • 对于遇到的每个 ‘(’ ,我们将它的下标放入栈中
    • 对于遇到的每个 ‘)’ ,我们先弹出栈顶元素表示匹配了当前右括号:

    如果栈为空,说明当前的右括号为没有被匹配的右括号,我们将其下标放入栈中来更新我们之前提到的「最后一个没有被匹配的右括号的下标」
    如果栈不为空,当前右括号的下标减去栈顶元素即为「以该右括号为结尾的最长有效括号的长度」

    我们从前往后遍历字符串并更新答案即可。

    需要注意的是,如果一开始栈为空,第一个字符为左括号的时候我们会将其放入栈中,这样就不满足提及的「最后一个没有被匹配的右括号的下标」,为了保持统一,我们在一开始的时候往栈中放入一个值为 −1 的元素。

    例如:( ) ) ( ( ( ) ) 

    代码如下:

        public int longestValidParentheses(String s) {
            int maxans = 0;
            Deque<Integer> stack = new LinkedList<Integer>();
            stack.push(-1);
            for (int i = 0; i < s.length(); i++) {
                if (s.charAt(i) == '(') {
                    stack.push(i);
                } else {
                    stack.pop();
                    if (stack.empty()) {
                        stack.push(i);
                    } else {
                        maxans = Math.max(maxans, i - stack.peek());
                    }
                }
            }
            return maxans;
        }
  • 相关阅读:
    Hibernate延迟加载
    java.io.FileNotFoundException: antlr-2.7.7.jar (系统找不到指定的路径。)[待解决]
    Eclipse中复制项目重命名后重新发布,项目名在地址栏仍然是原来的项目名”的问题
    Tomcat服务器启动失败:Could not publish server configuration for Tomcat v8.0 Server at localhost. Multiple Contexts have a path of
    SSH整合:Unable to instantiate Action, employeeAction, defined for 'emp-list' in namespace '/'employeeAction
    ApplicationContext详解以及多个ApplicationContext.xml的相互引用
    Tomcat启动失败:Server Tomcat v8.0 Server at localhost was unable to start within 45 seconds
    三大框架你理解多少?
    通过命令行查询可用的包的版本号
    使用create-react-app命令创建一个项目, 运行npm run eject报错
  • 原文地址:https://www.cnblogs.com/Vincent-yuan/p/14571674.html
Copyright © 2011-2022 走看看