算法题--寻找括号组成的字符串中最长合法子串的长度

image.png

0. 链接

1. 需求

Given a string containing just the characters '(' and ')', find the length of the longest valid (well-formed) parentheses substring.

Example 1:

Input: "(()"
Output: 2
Explanation: The longest valid parentheses substring is "()"

Example 2:

Input: ")()())"
Output: 4
Explanation: The longest valid parentheses substring is "()()"

2. 思路1: 暴力穷举

2.1 算法步骤

比如((())的所有可能的长度为2的倍数的子串如下

((          # invalid     
((()        # invalid
((          # invalid
(())        # valid, len=4
()          # valid, len=2
))          # invalid

2.2 代码

class SolutionBruteForce:
    def isValid(self, substr):
        stack = list()

        for ch in substr:
            if ch == '(':
                stack.append(ch)
            elif len(stack) > 0 and stack[-1] == '(':
                stack.pop(-1)
            else:
                return False

        return len(stack) == 0

    def longestValidParentheses(self, s: str) -> int:
        max_len = 0

        for i in range(len(s)):
            for j in range(i + 2, len(s) + 1, 2):
                if self.isValid(s[i:j]):
                    max_len = max(max_len, j - i)

        return max_len

2.3 结果

超时

3. 思路2: 动态规划

3.1 算法思路

从穷举法的结果可以总结出规律,

  • 所有的合法子串, 必定以)为结尾
  • 可能存在括号嵌套的可能

用动态规划,确定子问题为:定义dp[], 其中dp[i]表示以第i个字符为结尾往前追溯到的最长合法子串

例如

input: ()((()))
dp:    02000248

input: )()())
dp:    002040

3.2 算法步骤

定义max_len
定义dp[], 其中dp[i]表示以第i个字符为结尾往前追溯到的最长合法子串

则
    若s[i] == '(' 则dp[i] = 0
    若s[i] == ')'
        若s[i - 1] == '(' 则dp[i] = dp[i - 2] + 2
        若s[i - 1] == ')' 
            若s[i - 1 - dp[i - 1]] == '(' 则dp[i] = dp[i - 1] + 2 + dp[i - 2 - dp[i - 1]]

3.3 代码

def longestValidParentheses(self, s: str) -> int:
    max_len = 0
    dp = [0] * len(s)

    for i, ch in enumerate(s):
        if ch == ')' and i > 0:
            if s[i - 1] == '(':
                if i >= 2:
                    dp[i] = dp[i - 2] + 2
                else:
                    dp[i] = 2
            elif s[i - 1] == ')':
                inner_begin_index = i - 1 - dp[i - 1]
                if inner_begin_index >= 0 and s[inner_begin_index] == '(':
                    outter_begin_index = inner_begin_index - 1
                    if outter_begin_index >= 0:
                        dp[i] = dp[i - 1] + 2 + dp[outter_begin_index]
                    else:
                        dp[i] = dp[i - 1] + 2

            max_len = max(max_len, dp[i])

    return max_len

3.4 结果

image.png

你可能感兴趣的:(算法题--寻找括号组成的字符串中最长合法子串的长度)