返回

用动态规划解决 leetcode 中的「最长有效括号」难题

前端

最长有效括号:破解破解括号匹配的奥秘

序幕:理解问题本质

在「最长有效括号」难题中,我们被赋予一个只包含 '(' 和 ')' 的字符串,目标是找到字符串中最长的有效括号子串。所谓有效括号子串,是指左括号 '(' 和右括号 ')' 成对出现,且满足这样的条件:每个左括号都与它右侧的第一个右括号匹配。

例如,在字符串 "(()())" 中,最长的有效括号子串是 "()()"。而在字符串 "((()))))" 中,最长的有效括号子串是 "()()()”。

第一幕:动态规划的闪亮登场

动态规划是一种强大的算法范式,非常适合解决这类子问题相互重叠的问题。在「最长有效括号」难题中,我们可以定义一个状态 dp[i],其中 i 表示字符串的索引,dp[i] 表示从字符串的开头到索引 i 为止的最长有效括号子串的长度。

然后,我们可以根据以下状态转移方程来计算 dp[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] = dp[i-1] + dp[i-2] + 2,因为我们找到了一个新的更长的有效括号子串。否则,dp[i] = 0。

第二幕:代码片段的闪亮登场

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

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

    max_length = max(max_length, dp[i])

  return max_length

第三幕:优化与改进:锦上添花

为了进一步优化算法的性能,我们可以使用一些额外的技巧和优化方法:

  • 空间优化: 我们可以使用一个变量来存储当前最长有效括号子串的长度,而不是存储整个 dp 数组。这将大大降低算法的空间复杂度。
  • 剪枝: 在计算 dp[i] 时,我们可以使用剪枝来减少不必要的计算。例如,如果我们已经知道 dp[i-1] = 0,那么我们就无需计算 dp[i]。
  • 并行计算: 如果我们有多个处理器,我们可以使用并行计算来加快算法的运行速度。

尾声:掌握动态规划,开启算法新境界

「最长有效括号」难题只是动态规划众多应用场景中的一个示例。通过理解和掌握动态规划的精髓,您将能够解决更多复杂的问题,并成为一名更强大的算法工程师。

最后,希望这篇文章能够帮助您理解和解决「最长有效括号」难题。如果您有任何疑问或建议,请随时与我联系。