返回

算法必刷题[83]: 获取一个字符串的最大有效括号长度

前端




正文

在计算机编程中,算法是非常重要的一个环节。算法可以帮助我们快速有效地解决问题,并优化程序的运行效率。在算法的学习中,刷题是一个非常有效的方法。通过刷题,我们可以巩固所学知识,提升解决问题的能力,还能积累经验,为未来的工作打下坚实的基础。

今天,我们来刷一道经典的算法题,也是 LeetCode 上非常受欢迎的一道题:最长有效括号。

题目

给你一个只包含左括号和右括号的字符串,返回它最长的有效括号子序列的长度。

示例 1:

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

示例 2:

输入:s = "(()"
输出:2
解释:最长有效括号子序列是 "()"

示例 3:

输入:s = ""
输出:0
解释:没有有效括号子序列

解题思路

这道题可以用动态规划来求解。我们定义一个状态 dp[i],表示以第 i 个字符结尾的最长有效括号子序列的长度。那么,我们可以根据第 i 个字符是左括号还是右括号来更新 dp[i] 的值。

  • 如果第 i 个字符是左括号,那么 dp[i] 为 0,因为左括号无法匹配右括号,所以以第 i 个字符结尾的最长有效括号子序列的长度为 0。
  • 如果第 i 个字符是右括号,那么我们首先要检查第 i-1 个字符是否为左括号。如果是,那么 dp[i] 为 dp[i-2] + 2,因为我们可以把第 i-1 个左括号和第 i 个右括号匹配起来,并把它们前面的有效括号子序列也计入其中。如果第 i-1 个字符不是左括号,那么 dp[i] 为 0,因为无法匹配。

下面是动态规划的代码实现:

def longest_valid_parentheses(s):
  """
  :type s: str
  :rtype: int
  """
  n = len(s)
  dp = [0] * n

  for i in range(1, n):
    if s[i] == ')':
      if s[i-1] == '(':
        dp[i] = dp[i-2] + 2
      elif i >= 2 and s[i-1] == ')' and s[i-2] == '(':
        dp[i] = dp[i-2] + dp[i-3] + 2

  return max(dp)


# 测试代码
print(longest_valid_parentheses(")()())"))  # 4
print(longest_valid_parentheses("(()"))  # 2
print(longest_valid_parentheses(""))  # 0

复杂度分析

  • 时间复杂度:O(n),其中 n 为字符串 s 的长度。
  • 空间复杂度:O(n),其中 n 为字符串 s 的长度。

结语

这道题是算法必刷题中的经典题型,希望大家能够通过这道题的讲解,对动态规划算法有更深入的理解。刷题虽然重要,但更重要的是要理解算法背后的思想和原理,这样才能举一反三,触类旁通。祝大家刷题愉快!