给定一个只由左括号和右括号的字符串,返回最长的有效括号子串的长度。如何解答呢?

简介: 给定一个只由左括号和右括号的字符串,返回最长的有效括号子串的长度。如何解答呢?

要找到只包含左括号和右括号的字符串中最长的有效括号子串的长度,我们可以使用栈或动态规划的方法。这里我将为你提供动态规划的解决方案。

动态规划的思路是,我们遍历整个字符串,对于每个位置,我们维护一个数组 dp,其中 dp[i] 表示以第 i 个字符结尾的最长有效括号子串的长度。

遍历字符串时,我们需要考虑以下几种情况:

如果当前字符是左括号,那么它不能形成有效括号子串,所以 dp[i] = 0。

如果当前字符是右括号,我们需要看其前面是否有对应的左括号可以匹配。如果前面没有左括号,那么 dp[i] = 0。如果前面有左括号,那么我们需要看左括号之前的子串是否也是有效括号子串。如果是,那么 dp[i] 的值就是左括号之前的有效子串长度加上当前右括号和前面的左括号。

但是,这里还有一个问题:如何快速找到左括号之前的有效子串长度?我们可以使用一个栈来辅助解决这个问题。当遇到左括号时,我们将其索引压入栈中;当遇到右括号时,如果栈不为空,说明有左括号可以匹配,我们弹出栈顶元素(即左括号的索引),并计算当前有效子串的长度。如果栈为空或者栈顶元素之前有更长的有效子串,我们还需要加上那部分长度。

下面是具体的实现步骤:

初始化一个空栈 stack 和一个长度为 n(字符串长度)的数组 dp,其中 dp[i] 初始值都为 0。

遍历字符串的每个字符:

如果当前字符是左括号,将其索引压入栈中。

如果当前字符是右括号:

如果栈为空,说明没有左括号可以匹配,dp[i] = 0。

否则,弹出栈顶元素,记为 leftIndex。

如果栈不为空,说明 leftIndex 之前有更长的有效子串,我们需要加上那部分长度,即 dp[i] = dp[leftIndex - 1] + 2。

如果栈为空,说明 leftIndex 就是当前有效子串的起点,dp[i] = 2。

还需要考虑 leftIndex 之前的子串是否有更长的有效子串,如果有,则 dp[i] += dp[leftIndex - 1]。

遍历完整个字符串后,dp 数组中的最大值就是最长的有效括号子串的长度。

下面是 Python 代码实现:


python复制代码
 def longestValidParentheses(s):  
 
     stack = []  
 
     dp = [0] * len(s)  
 
     max_length = 0  
 
       
 
     for i in range(len(s)):  
 
         if s[i] == '(':  
 
             stack.append(i)  
 
         else:  
 
             if stack:  
 
                 left_index = stack.pop()  
 
                 if stack:  
 
                     dp[i] = dp[left_index - 1] + 2  
 
                 else:  
 
                     dp[i] = 2  
 
                 if left_index > 0:  
 
                     dp[i] += dp[left_index - 1]  
 
             max_length = max(max_length, dp[i])  
 
       
 
     return max_length


这个算法的时间复杂度是 O(n),其中 n 是字符串的长度。我们只需要遍历一次字符串,并使用栈来辅助计算。空间复杂度也是 O(n),用于存储 dp 数组和栈。


相关文章
|
7月前
|
存储
【字符串】最长不含重复字符的子字符串
【字符串】最长不含重复字符的子字符串
|
索引
【LeetCode】917. 仅仅反转字母、387. 字符串中的第一个唯一字符
目录 917. 仅仅反转字母 387. 字符串中的第一个唯一字符
51 0
|
7月前
|
算法 测试技术 C#
【线段树】2213. 由单个字符重复的最长子字符串
【线段树】2213. 由单个字符重复的最长子字符串
|
7月前
|
索引
leetcode-1624:两个相同字符之间的最长子字符串
leetcode-1624:两个相同字符之间的最长子字符串
36 0
|
Java
给定一个字符串和一个子串。子串中的字符可能重复,输出子串出现的次数。(Java实现)
给定一个字符串和一个子串。子串中的字符可能重复,输出子串出现的次数。(Java实现)
120 0
给定一个字符串和一个子串。子串中的字符可能重复,输出子串出现的次数。(Java实现)
在一个由小写英文字母(a-z)组成的字符串中,查找最短子串,其头尾字母相同。输出最左边的该类子串。
在一个由小写英文字母(a-z)组成的字符串中,查找最短子串,其头尾字母相同。输出最左边的该类子串。
77 0
在一个由小写英文字母(a-z)组成的字符串中,查找最长子串,其头尾字母相同,且中间不包含该头尾字母,并输出最左边的该类子串
在一个由小写英文字母(a-z)组成的字符串中,查找最长子串,其头尾字母相同,且中间不包含该头尾字母,并输出最左边的该类子串
168 0
遍历所有子串,回文串,公共前缀,旋转字符串
遍历所有子串,回文串,公共前缀,旋转字符串
98 0
|
存储
【LeetCode】第8天 - 3. 无重复字符的最长子串 | 567 字符串的排列
【LeetCode】第8天 - 3. 无重复字符的最长子串 | 567 字符串的排列
105 0
【LeetCode】第8天 - 3. 无重复字符的最长子串 | 567 字符串的排列