`
frank-liu
  • 浏览: 1666090 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

leetcode: 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.

原问题链接:https://leetcode.com/problems/longest-valid-parentheses/

 

问题分析

    在求最长合法的括号串之前,我们先来看一下如果给定一个字符串,如果要判断它是否为合法的括号串该怎么做。 在之前的一些文章里也讨论过,要处理这样的问题,可以用一个栈。遍历字符串中间每个元素的时候每次碰到左括号的时候就将它入栈,碰到右括号的时候就来查看栈的情况。如果栈非空而且栈顶的元素是左括号则表示当前找到一对匹配的括号。我们会将当前栈顶的元素弹出来。否则表示当前的串不是一个合法的符号串。在遍历结束后如果栈是空的,表示这整个串是合法的括号串,否则表示非法的串。

  上述描述的判断一个串是否为合法括号串的方法有一个特点,如果它整体是合法的,则参与运算的栈最终是空的。在目前的问题里,给定的一个串可能里面部分串是一个合法的括号串,也可能它整个本身就是一个合法的括号串。那么我们针对这些情况来讨论一下。

  很明显,当按照前面的过程,如果最后整个栈是空的,也就是说整个串就是合法的串,那么很简单,我们直接返回这个串的长度就可以了。那么对于它部分是合法串的情况呢?在遍历的过程中必然会有一些元素存在于栈中。这些在栈中的元素相当于一个个的分隔点,在这些点之间如果存在有空隙的话,这些空隙其实就相当于一些合法串。所以我们最终就是要在遍历完之后找到这些长度最大的空隙,也就找到了最长的括号串。有了上述的思路,在实现的时候还可以稍微做一些修改。

  我们在每次碰到当前字符为')'而且栈顶元素为'('的时候,表示当前找到了一个匹配。这个时候我们要求的最长的段应该是从当前的索引i到栈里头除了栈顶这个元素之后的那个元素之间距离。因为按照前面的推理,还留在栈里的元素就是针对当前长度来说没有找到匹配的。所以只要计算一下当前元素和这个元素后面那个元素之间的距离就可以了。当然,还有一些边界条件,比如说除了匹配的'('之后当前的栈已经空了,这说明我们匹配到串的最开始。为了统一各种条件,我们可以在最开始向栈里加入一个元素-1。以后碰到的元素只要和匹配的'('下面的那个元素相减就可以了。具体的实现见如下的代码:

 

public class Solution {
    public int longestValidParentheses(String s) {
        Stack<Integer> stack = new Stack<>();
        int result = 0;
        stack.push(-1);
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == ')' && stack.size() > 1 && s.charAt(stack.peek()) == '(') {
                stack.pop();
                result = Math.max(result, i - stack.peek());
            } else {
                stack.push(i);
            }
        }
        return result;
    }
}

 

 

另一种解法

    其实这个问题还有另外一种解决思路。就是我们从左到右遍历整个字符串的时候,一个合格的括号串它是在任何一个位置保证左括号的数量大于等于右括号的数量的。所以我们可以用一个数字来记录当前左括号的数量。当碰到一个左括号的时候这个数字就加一,碰到右括号的时候如果本身左括号的数量大于零,就表示找到了一个匹配,将左括号数减一。

    当然,如果只是这样子还是不能得到最长合法括号串。我们需要定义一个和字符串等长的整型数组,用来记录当前某个位置所匹配的长度。比如说我们有串"()",在索引0的位置匹配的长度为0,而在索引1的位置,它匹配的长度为2。

  对于数组中任意的一个位置i来说,当碰到一个匹配的时候dp[i] = dp[i - 1] + 2。当然,这里是否就概括了所有的情况呢?针对"(())"这种类型的来说,我们一个右括号碰到的和它匹配的左括号不是在它连着的左边,或者在数组的开头有"()"。针对这种情况dp[i] = dp[i - 1] + 2确实是成立的。但是还有一些情况就是它们匹配的情况之前还有一部分。比如说"()()",针对索引3的位置来说,它得到的值是2。但是在它之前还有一个匹配的部分,这里真实的最长的合法串应该还要加上前面那个位置的匹配。所以应该是dp[i] += dp[i - dp[i]]。当然,在具体的实现中要保证i - dp[i] >= 0。所以按照这种方式得以得到如下的一个实现:

 

public class Solution {
    public int longestValidParentheses(String s) {
        int[] dp = new int[s.length()];
        int result = 0;
        int leftCount = 0;
        for (int i = 0; i < s.length(); i++) {
            if (s.charAt(i) == '(') {
                leftCount++;
            } else if (leftCount > 0){
                dp[i] = dp[i - 1] + 2;
                dp[i] += (i - dp[i]) >= 0 ? dp[i - dp[i]] : 0;
                result = Math.max(result, dp[i]);
                leftCount--;
            }
        }
        return result;
    }
}

  这种实现不需要使用栈来保存匹配的位置信息,减少了一些入栈和出栈的操作,所以整体的执行效率更加高。整体的时间复杂度在O(N)的范围。

 

总结

  判断合法括号串的方法有一个固定的套路。但是在结合具体问题来讨论,比如在一个串里找最大合法括号串的时候,我们可以利用合法串里左括号和右括号数量相等而且任何位置都是左括号数量大于等于右括号数量的条件。在第二种方法里,我们通过一个判断dp[i]和dp[i - dp[i]]的位置关系可以将一些连续的合法串的长度计算出来,避免了还需要后面回头去遍历计算。

 

参考材料

https://leetcode.com/discuss/83428/java-solutions-with-explanation-stack-short-easy-understand

分享到:
评论

相关推荐

    javalruleetcode-LeetCode::lollipop:个人LeetCode习题解答仓库-多语言

    java lru leetcode :ice_cream: LeetCode ...Parentheses 26 Remove Duplicates from Sorted Array 48 Rotate Image 53 Maximum Subarray 55 Jump Game 56 Merge Intervals 64 Minimum Path Sum 73

    lrucacheleetcode-leetcode:leetcode

    Valid Parentheses 21. Merge Two Sorted Lists 22. Generate Parentheses 25. Reverse Nodes in k-Group 26. Remove Duplicates from Sorted Array 27. Remove Element 28. Implement strStr() 3

    leetcode中国-leetcode:leetcode刷题

    Parentheses 用栈判断括号匹配 Regular Expression Matching 递归匹配 wildcard matching 动态规划 longest common prefix , 简单 valid number, hard, 用有限自动机 integer to roman ,easy , 模拟 roman to ...

    leetcode题库-LeetCode:力码

    leetcode题库 LeetCode 题解合集 本仓库展示了LeetCode题库中部分题目的解法(持续更新),所有代码均采用C++编写并配有输入输出样例 代码清单如下: 序号 题目 程序源码 ...Parentheses.cpp 22 括号生成 G

    leetcode双人赛-LeetCode:力扣笔记

    leetcode双人赛LeetCode 编号 题目 难度 题型 备注 Two Sum 简单 Add Two Numbers 中等 链结串列 重要 Longest Substring Without Repeating Characters 中等 字串 重要 Median of Two Sorted Arrays 困难 数学 ...

    JavaScript数据结构之栈实例用法

    Leetcode 32 Longest Valid Parentheses (最长有效括号) 给定一个只包含 ‘(‘ 和 ‘)’ 的字符串,找出最长的包含有效括号的子串的长度。 示例 1: 输入: “(()” 输出: 2 解释: 最长有效括号子串为 “()” 示例 2...

    leetcode怎么改密码-Code:学会学习

    leetcode怎么改密码 Code leetcode easy 测试一下本地的... emmmmm之前修改了一下,现在用ssh提交 应该不用输入密码了吧 ~~emmmmm 先在这里立个flag!!...Longest Valid Parentheses :cross_mark:暴力解法(未通过)

    颜色分类leetcode-leetcode-[removed]我对Leetcode问题的解决方案

    颜色分类leetcode My Leetcode Problems Solutions Using javascript(ES6) 1 Two Sum 两数之和 5 Longest Palindromic Substring 最长回文子串 7 Reverse Integer 整数反转 9 Palindrome Number 回文数 11 Container...

    javalruleetcode-learn-algorithms::laptop:Java实现的各种算法题解

    java lru leetcode ...Parentheses](./leetcode/动态规划-Longest Valid Parentheses.java) [动态规划-Maximum Length of Repeated Subarray](./leetcode/动态规划-Maximum Length of Repeated Subar

    LeetCode最全代码

    # [LeetCode](https://leetcode.com/problemset/algorithms/) ![Language](https://img.shields.io/badge/language-Python%20%2F%20C++%2011-orange.svg) [![License]...

    程序员面试宝典LeetCode刷题手册

    第四章 Leetcode 题解 ...20. Valid Parentheses 21. Merge Two Sorted Lists 22. Generate Parentheses 23. Merge k Sorted Lists 24. Swap Nodes in Pairs 25. Reverse Nodes in k-Group 26. Remove Dupli

    leetcode530-algorithm:算法

    leetcode 530 ** LeetCode 题目更新 ** 用来记录业余时间所做的算法题目,保持对于数据结构的熟悉。 ** ...Valid Parentheses 022 Generate Parentheses 028 Implement strStr() 031 Next Permutat

    javalruleetcode-leetcode-java:力码笔记

    Parentheses 26.Remove Duplicates from Sorted Array 53.Maximum Subarray 70.Climbing Stairs 121.Best Time to Buy and Sell Stock 122.Best Time to Buy and Sell Stock II 123.Best Time to Buy and Sell Stock...

    leetcode2-Algorithms-Practice:创建此repo是为了跟踪我在解决问题方面的进展

    Longest Common Prefix 运行时间:40 毫秒内存使用:13.9 MB 20. Valid Parentheses 运行时间:40 毫秒内存使用:13.8 MB 22. Generate Parentheses 运行时间:164 毫秒内存使用:22.5 MB 26. Remove Duplicates ...

    丢失的最小正整数leetcode-LeetCodePractice:我的LeetCode练习

    丢失的最小正整数leetcode LeetCode Note 7. ...Parentheses: 对于括号匹配问题,自然而然的想到利用栈来实现。也成功实现了括号匹配,再去一观其他人答案,实际可引入map去提前设置好匹配规则,这

    gasstationleetcode-leetcode-rust:莱特代码休息

    加油站 leetcode 力码锈 问题 # 标题 命令 1 cargo run ...3-longest-substring-without-repeating-...20-valid-parentheses 21 cargo run --bin 21-merge-two-sorted-lists 27 cargo run --bin 27-remove-element 28

    lrucacheleetcode-Algorithm:一些常见的算法的解题报告

    lru cache leetcode #算法解题报告 主要记录我每天做的题目,包括leetcode, 剑指offer等在线编程平台,以前做过的等时间够再一起分享。 使用swift解题 30-Day ...Parentheses 21.Merge Two Sorted L

    LeetCode去除数组重复元素-leetcode_[removed]刷题

    LeetCode去除数组重复元素 说明 在leetcode上的题目 ...Parentheses(有效的括号) 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。 有效字符串需满足:左括号必须用相同类型的

    cpp-算法精粹

    Longest Valid Parentheses Largest Rectangle in Histogram Evaluate Reverse Polish Notation Implement Stack using Queues 队列 Implement Queue using Stacks 二叉树 二叉树的遍历 Binary Tree Preorder ...

Global site tag (gtag.js) - Google Analytics