LeetCode-32 最长有效括号

简介: LeetCode-32 最长有效括号

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-valid-parentheses

题目描述

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

 

示例 1:
输入:s = "(()"
输出:2
解释:最长有效括号子串是 "()"
示例 2:
输入:s = ")()())"
输出:4
解释:最长有效括号子串是 "()()"
示例 3:
输入:s = ""
输出:0
提示:
0 <= s.length <= 3 * 104
s[i] 为 '(' 或 ')'

 

解题思路

本题有三种解法,分别是动态规划法,栈法和两次遍历法。

动态规划法比较难想,我们使用一个dp数组来记录有效括号的长度,对于“(”来说,可以形成的有效括号总为0,因为需要有右括号才能形成有效括号。对于“)”来说,需要考虑三个部分,首先是对于第i个位置的右括号,需要判断第i - dp[i - 1] - 1的位置是否为左括号,如果不是左括号,那么就无法构成有效括号,dp[i] = 0,如果是,则有效括号长度可以+2,这个时候考虑第i个括号内部的长度,所以dp[i] += dp[i - 1],最后,我们还得考虑第i个括号对应的左括号前面有效括号的长度,所以dp[i] += dp[i - dp[i - 1] - 1],所以,递推公式为dp[i] = dp[i - dp[i - 1] - 1] + dp[i - 1] + 2(假设三个部分都为有效括号)

栈法和括号匹配的栈方法规则不太一样,提前将栈加入-1,方便边界处理,对于"("来说,入栈就可以了,对于")"来说,如果栈顶元素是-1或者是")"那么这个右括号是无效的括号直接入栈,如果栈顶元素是"("那么直接将栈顶出栈,这个右括号对应的最长有效括号长度就为这个右括号的下标减去了现在的栈顶元素。

双向遍历法其实才是刚刚开始想到的一个,只不过刚刚开始只想到了单向遍历,可以使用left 和right同时记录左右括号的个数,如果left = right 说明是有效括号,将其长度与最长长度比较并记录,如果left < right说明当前括号非法,将left与right全部置0,但是有个问题是这种方法容易漏掉"(()"这种情况,在这种情况下,left和right永远不能相等,这个时候可以从右往左再来一次遍历,操作方法和之前遍历类似,那么从右往左的遍历将漏掉"())"的情况,将两种遍历结合起来,就可以覆盖所有情况了。

代码展示

动态规划法:

class Solution {
public:
    int longestValidParentheses(string s) {
        vector<int> dp(s.size(), 0);
        if(s.size() == 0) return 0;
        int Max = 0;
        for (int i = 0; i < s.size(); i++)
        {
            if (s[i] == '(')
            {
                dp[i] = 0;
            }
            else
            {
                if (i - 1 >= 0)
                {
                    if(s[i - 1] == '(')
                    {
                        dp[i] = (i - 2 >= 0 ? dp[i - 2] : 0) + 2;
                    }
                    else
                    {
                        if(i - dp[i - 1] - 1 >= 0 && s[i - dp[i - 1] - 1] == '(')
                            dp[i] = (i - dp[i - 1] - 2 >= 0 ? dp[i - dp[i - 1] - 2] : 0 ) + dp[i - 1] + 2;
                        else
                            dp[i] = 0;
                    }
                }
            }
        }
        for (auto iter : dp)
            Max = max(Max, iter);
        return Max;
    }
};

栈法:

class Solution {
public:
    int longestValidParentheses(string s) {
        stack<int> siStack;
        int iMax = 0;
        siStack.push(-1);
        for(int i = 0; i < s.size(); i++)
        {
            if(s[i] == '(')
            {
                siStack.push(i);
            }
            else
            {
                int top = siStack.top();
                if(top == -1 || s[top] == ')')
                    siStack.push(i);
                else
                {
                    siStack.pop();
                    int iCount = i - siStack.top();
                    if(iCount > iMax)
                        iMax = iCount;
                }
            }
        }
        return iMax;
    }
};

 

两次遍历法:

class Solution {
public:
    int longestValidParentheses(string s) {
        int iMax = 0;
        int left = 0, right = 0;
        for(int i = 0; i < s.size(); i++)
        {
            if(s[i] == '(')
                left++;
            else
            {
                right++;
                if(left < right)
                {
                    left = 0;
                    right = 0;
                }
                else if(left == right)
                {
                    if(2* right > iMax)
                        iMax = 2* right;
                }
            }
        }
        left = right = 0;
         for(int i = s.size() - 1; i >= 0; i--)
        {
            if(s[i] == ')')
                right++;
            else
            {
                left++;
                if(left > right)
                {
                    left = 0;
                    right = 0;
                }
                else if(left == right)
                {
                    if(2* left > iMax)
                        iMax = 2* left;
                }
            }
        }
        return iMax;
    }
};

 

运行结果

 

相关文章
|
6月前
|
存储 C语言 索引
环形链表、环形链表 II、有效的括号​​​​​​​【LeetCode刷题日志】
环形链表、环形链表 II、有效的括号​​​​​​​【LeetCode刷题日志】
|
2天前
|
存储 算法 Java
leetcode算法题-有效的括号(简单)
【11月更文挑战第5天】本文介绍了 LeetCode 上“有效的括号”这道题的解法。题目要求判断一个只包含括号字符的字符串是否有效。有效字符串需满足左括号必须用相同类型的右括号闭合,并且左括号必须以正确的顺序闭合。解题思路是使用栈数据结构,遍历字符串时将左括号压入栈中,遇到右括号时检查栈顶元素是否匹配。最后根据栈是否为空来判断字符串中的括号是否有效。示例代码包括 Python 和 Java 版本。
|
1月前
|
算法 C++
Leetcode第二十二题(括号生成)
这篇文章讨论了如何使用递归算法解决LeetCode第22题“括号生成”的问题,提供了两种C++的实现方法,目的是生成所有有效的括号组合。
13 0
Leetcode第二十二题(括号生成)
|
1月前
|
存储 C++ 容器
Leetcode第二十题(有效的括号)
这篇文章介绍了如何使用栈来解决LeetCode第20题“有效的括号”问题,提供了两种方法:数组栈和容器栈,以及相应的C++代码实现。
16 0
|
3月前
|
算法
LeetCode第22题括号生成
该文章介绍了 LeetCode 第 22 题括号生成的解法,通过回溯算法生成所有可能的括号组合,在递归过程中根据左右括号数量的条件进行剪枝,从而得到有效的括号组合。
LeetCode第22题括号生成
|
3月前
|
存储 算法
LeetCode第20题有效的括号
该文章介绍了 LeetCode 第 20 题有效的括号的解法,通过分析有效括号的特征,使用栈结构存储括号关系,判断遇到右边括号时栈顶是否有匹配的左边括号,从而解决问题,同时总结了栈的先进后出结构可用于解决有规律的符号匹配问题。
LeetCode第20题有效的括号
|
3月前
|
算法 Python
【Leetcode刷题Python】括号匹配问题
一种解决括号匹配问题的Python实现方法,通过计算给定括号串的所有子串的最长合法括号子序列长度之和来确定权值。
23 0
|
3月前
|
机器学习/深度学习 Python
【Leetcode刷题Python】22. 括号生成
本文介绍了了LeetCode题目22的两种Python编程解决方案,题目要求生成所有可能的且有效的括号组合,包括暴力求解和回溯方法。
23 0
|
3月前
|
Python
【Leetcode刷题Python】20. 有效的括号
LeetCode上题目“20. 有效的括号”的Python解决方案,使用栈数据结构来验证括号序列的有效性。具体实现中,会在栈中预先放置一个特殊字符以避免在弹出操作时出现空栈错误,并通过匹配左右括号来判断括号序列是否有效。
41 0
|
5月前
|
算法 Java C语言
【经典算法】LeetCode 20:有效的括号(Java/C/Python3实现含注释说明,Easy)
【经典算法】LeetCode 20:有效的括号(Java/C/Python3实现含注释说明,Easy)
40 1