LeetCode 题目 32:最长有效括号【python】

简介: LeetCode 题目 32:最长有效括号【python】

作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。

会一些的技术:数据分析、算法、SQL、大数据相关、python

欢迎加入社区:码上找工作

作者专栏每日更新:

LeetCode解锁1000题: 打怪升级之旅

python数据分析可视化:企业实战案例

备注说明:方便大家阅读,统一使用python,带必要注释,公众号 数据分析螺丝钉 一起打怪升级

问题描述

给定一个只包含 '('')' 的字符串,找出最长的包含有效括号的子串的长度。

示例 1

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

示例 2:

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

示例 3:

输入:s = ""
输出:0

这个问题可以通过几种不同的方法来解决,包括动态规划、栈和不使用额外空间的扫描法。

方法一:动态规划

动态规划是解决此类问题的一个非常直观的方法。我们可以定义一个 dp 数组,其中 dp[i] 表示以 s[i] 结尾的最长有效括号的长度。

实现步骤

  1. 初始化:创建一个长度为 n+1 的数组 dp,所有值初始化为 0。
  2. 状态转移
  • 如果 s[i]')'s[i-1]'(',则 dp[i] = dp[i-2] + 2
  • 如果 s[i]')'s[i-1]')'s[i-dp[i-1]-1]'(',则 dp[i] = dp[i-1] + dp[i-dp[i-1]-2] + 2
  1. 计算结果:最大值在 dp 数组中取得。

代码示例

def longestValidParentheses(s):
    n = len(s)
    dp = [0] * (n + 1)
    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

方法二:栈

使用栈是另一种常见的解决方案,可以有效地追踪未匹配的括号。

实现步骤

  1. 初始化栈:栈中预先压入 -1,表示最后一个未匹配的右括号的位置。
  2. 遍历字符串
  • 如果 s[i]'(',将 i 压栈。
  • 如果s[i]')'
  • 弹出栈顶元素。
  • 如果栈为空,将当前索引 i 压栈。
  • 如果栈不为空,更新结果 max_length = max(max_length, i - stack[-1])

代码示例

def longestValidParentheses(s):
    max_length = 0
    stack = [-1]
 
    for i in range(len(s)):
        if s[i] == '(':
            stack.append(i)
        else:
            stack.pop()
            if not stack:
                stack.append(i)
            else:
                max_length = max(max_length, i - stack[-1])
    
    return max_length

方法三:不使用额外空间的扫描法

实现步骤

  1. 第一遍扫描(从左到右):
  • 初始化两个计数器left 为左括号计数器,right 为右括号计数器,初始化为0。
  • 遍历字符串:对字符串s的每一个字符进行遍历。
  • 增加计数器:如果字符是 '(',增加 left 计数器;如果字符是 ')',增加 right 计数器。
  • 计算有效长度
  • left 计数器等于 right 计数器时,计算当前有效的括号长度,即 2 * right(或 2 * left,因为此时 left == right),并更新最大长度 maxlength
  • 如果 right 计数器大于 left 计数器,说明括号已经无法闭合,需要重置两个计数器为0,重新开始计数。
  1. 第二遍扫描(从右到左):
  • 重新初始化计数器:同样,leftright 初始化为0,但此次遍历的目的是捕捉如 (() 这类左括号多于右括号的情况。
  • 逆向遍历字符串:从字符串的最后一个字符向前遍历。
  • 增加计数器:如果字符是 '(',增加 left 计数器;如果字符是 ')',增加 right 计数器。
  • 计算有效长度
  • left 计数器等于 right 计数器时,计算当前有效的括号长度,即 2 * left,并更新最大长度 maxlength
  • 如果 left 计数器大于 right 计数器,说明左括号过多,括号无法闭合,需要重置两个计数器为0,重新开始计数。

代码示例

def longestValidParentheses(s):
    left = right = maxlength = 0
 
    # Left to right
    for char in s:
        if char == '(':
            left += 1
        else:
            right += 1
        if left == right:
            maxlength = max(maxlength, 2 * right)
        elif right > left:
            left = right = 0
 
    left = right = 0
    # Right to left
    for char in reversed(s):
        if char == '(':
            left += 1
        else:
            right += 1
        if left == right:
            maxlength = max(maxlength, 2 * left)
        elif left > right:
            left = right = 0
 
    return maxlength

总结

选择哪种方法取决于具体的应用场景和空间时间的权衡:

  • 如果内存资源不是问题,可以优先考虑使用 动态规划 方法,因为它们易于实现和理解。
  • 如果需要优化空间消耗,双向扫描 提供了一个不使用额外空间的有效解决方案。

以上分析展示了每种方法在解决 "最长有效括号" 问题时的性能和适用性,可以根据实际需求灵活选择最合适的方法。


欢迎关注微信公众号 数据分析螺丝钉

相关文章
|
18小时前
|
C语言
详解Leetcode中关于malloc模拟开辟二维数组问题,涉及二维数组的题目所给函数中的各个参数的解读
详解Leetcode中关于malloc模拟开辟二维数组问题,涉及二维数组的题目所给函数中的各个参数的解读
6 1
|
11天前
|
存储 算法 调度
力扣中级算法(Python)
力扣中级算法(Python)
|
11天前
|
算法 Python
力扣初级算法(Python)(二)
力扣初级算法(Python)(二)
|
12天前
|
算法
【经典LeetCode算法题目专栏分类】【第10期】排序问题、股票问题与TOP K问题:翻转对、买卖股票最佳时机、数组中第K个最大/最小元素
【经典LeetCode算法题目专栏分类】【第10期】排序问题、股票问题与TOP K问题:翻转对、买卖股票最佳时机、数组中第K个最大/最小元素
|
12天前
|
容器
【LeetCode刷题】栈和队列题目练习~
【LeetCode刷题】栈和队列题目练习~
【42页动态规划学习笔记分享】动态规划核心原理详解及27道LeetCode相关经典题目汇总(4)
【42页动态规划学习笔记分享】动态规划核心原理详解及27道LeetCode相关经典题目汇总
|
12天前
|
存储 算法
【42页动态规划学习笔记分享】动态规划核心原理详解及27道LeetCode相关经典题目汇总(1)
【42页动态规划学习笔记分享】动态规划核心原理详解及27道LeetCode相关经典题目汇总
|
12天前
|
算法
【经典LeetCode算法题目专栏分类】【第11期】递归问题:字母大小写全排列、括号生成
【经典LeetCode算法题目专栏分类】【第11期】递归问题:字母大小写全排列、括号生成
|
12天前
|
算法
【经典LeetCode算法题目专栏分类】【第9期】深度优先搜索DFS与并查集:括号生成、岛屿问题、扫雷游戏
【经典LeetCode算法题目专栏分类】【第9期】深度优先搜索DFS与并查集:括号生成、岛屿问题、扫雷游戏
|
12天前
|
算法
【经典LeetCode算法题目专栏分类】【第8期】滑动窗口:最小覆盖子串、字符串排列、找所有字母异位词、 最长无重复子串
【经典LeetCode算法题目专栏分类】【第8期】滑动窗口:最小覆盖子串、字符串排列、找所有字母异位词、 最长无重复子串