3. 数据结构---栈
一、栈
二、算法
1.括号匹配
Leetcode 20: 有效的括号
题目描述:
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
示例:
示例 1:
输入: "()"
输出: true
示例 2:
输入: "()[]{}"
输出: true
示例 3:
输入: "(]"
输出: false
示例 4:
输入: "([)]"
输出: false
示例 5:
输入: "{[]}"
输出: true
【思路】用栈保存括号的左半部分,遇到左半部分就入栈;遇到右半部分就查看栈顶元素是否与该括号为一对,如果是,就将栈顶元素出栈,否则,返回错误,表示该串括号无效。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | def isValid(s): stack_ = [] if s = = '': return True if len (s) = = 1 : return False list_s = list (s) for i in range ( len (list_s)): if list_s[i] = = '(' or list_s[i] = = '[' or list_s[i] = = '{' : stack_.append(s[i]) else : print ( 'stack_' ,stack_) if len (stack_) > 0 : if stack_[ - 1 ] = = None : return False if list_s[i] = = ')' and stack_[ - 1 ] ! = '(' : return False elif list_s[i] = = ']' and stack_[ - 1 ] ! = '[' : return False elif list_s[i] = = '}' and stack_[ - 1 ] ! = '{' : return False if list_s[i] and stack_ = = []: return False stack_ = stack_[: - 1 ] return stack_ = = [] res = isValid( '[]]' ) print (res) |
Leetcode 32: 最长有效括号
题目描述:给定一个只包含 '(' 和 ')' 的字符串,找出最长的包含有效括号的子串的长度。
示例:
示例 1:
输入: "(()"
输出: 2
解释: 最长有效括号子串为 "()"
示例 2:
输入: ")()())"
输出: 4
解释: 最长有效括号子串为 "()()"
思路:基于判断括号有效子集的方法扩展,主要思想是扫描字符串,遇到“(”的时候,将对应的index存储在stack中,遇到“)”的时候,意味着可能遇到了一个有效子字符串,所以需要维护一个maximam变量。 计算maximum的方法是,存一个start变量,是我们认为的有效的子集开始的位置,然后遍历字符串,利用不同的位置减去start得到的值,来维护maximum。
时间复杂度:O(n)
空间复杂度:O(n)
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | def longestValidParentheses(s): stack = [] start = 0 maximum = 0 for i in range ( len (s)): if s[i] = = '(' : stack.append(i) else : if stack = = []: start = i + 1 else : stack.pop() if stack ! = []: #说明是)前面紧跟着( maximum = max (maximum,i - stack[ - 1 ]) else : #说明)前面有不止一个(,就要计算start到当前i的距离 maximum = max (maximum,i - start + 1 ) return maximum |
Leetcode 856: 括号的分数
题目描述:
给定一个平衡括号字符串S,按下述规则计算该字符串的分数:
()得1分。
AB得A + B分,其中A和B是平衡括号字符串。
(A)得2 * A分,其中A是平衡括号字符串。
示例:
示例1:
输入: "()"
输出: 1
示例2:
输入: "(())"
输出: 2
示例3:
输入: "()()"
输出: 2
示例4:
输入: "(()(()))"
输出: 6
提示:S是平衡括号字符串,且只含有(和)。2 <= S.length <= 50
思路1:递归
对给定的字符串,找出与最左边的括号相匹配的右括号的下标index,如果这两个括号正好占据了字符串一左一右的两侧边界,则最后的分数为这两个括号中间部分的子字符串的分数 * 2。否则最后的分数等于下标index将S分成的左右两个平衡括号字符串分数之和。
思路2:栈
括号匹配的题目一般要用到栈,这个题也是。我们用栈保存两样东西:一是左括号(,二是得分。这样我们在遇到)返回的时候,可以直接判断栈里面是左括号还是得分。
如果是左括号(,那么得分是1,放入栈中。
如果是得分,那么我们需要一直向前求和直到找到左括号为止,然后把这个得分×2,放入栈中。
由于题目给的是符合要求的括号匹配对,那么栈里面最后应该只剩下一个元素了,就是最终得分。
思路1代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | from collections import OrderedDict class Solution ( object ): # 找第一个左括号的右括号对应的右括号的位置 def FindFirstRightkh( self ,S): stack = [] dict_S = OrderedDict() for idx,s in enumerate ( list (S)): if s = = '(' : stack.append(idx) elif s = = ')' and len (stack) > = 1 : dict_S[stack[ - 1 ]] = idx if stack[ - 1 ] = = 0 : return idx stack.pop() # print(dict_S) #{1: 2, 4: 5, 3: 6, 0: 7} def scoreOfParentheses( self , S): score = 0 if S = = '()' : return 1 elif S = = '(())' : return 2 elif S = = '()()' : return 2 idx_Rightkh = self .FindFirstRightkh(S) if idx_Rightkh = = len (S) - 1 : score = 2 * self .scoreOfParentheses(S[ 1 :idx_Rightkh]) else : score = self .scoreOfParentheses(S[:idx_Rightkh + 1 ]) + self .scoreOfParentheses(S[idx_Rightkh + 1 :]) return score |
思路2代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | class Solution1 ( object ): def scoreOfParentheses1( self , S): """ :type S: str :rtype: int """ scoreStack = [] for c in S: if c = = '(' : #如果是'(',就将-1入栈 scoreStack.append( - 1 ) else : #右括号 score = 0 while scoreStack[ - 1 ] ! = - 1 : #如果是得分,就一直加,直到遇到-1,得到内部的括号之和 score + = scoreStack.pop() scoreStack.pop() #弹出不是-1的 if score = = 0 : scoreStack.append( 1 ) else : #得分不为0,说明栈顶不为-1,得2倍分 scoreStack.append( 2 * score) totalScore = 0 while scoreStack ! = []: totalScore + = scoreStack.pop() return totalScore s = Solution() res = s.scoreOfParentheses(S = '((())(()))' ) print (res) |
Leetcode 921: 使括号有效的最少添加
题目描述:给定一个由'('和')'括号组成的字符串S,我们需要添加最少的括号( '('或是')',可以在任何位置),以使得到的括号字符串有效
说明:从形式上讲,只有满足下面几点之一,括号字符串才是有效的:
它是一个空字符串,或者它可以被写成AB(A与B连接), 其中A和B都是有效字符串,或者它可以被写作 (A),其中A是有效字符串。
给定一个括号字符串,返回为使结果字符串有效而必须添加的最少括号数。
示例1:
输入:"())"
输出:1
示例2:
输入:"((("
输出:3
示例3:
输入:"()"
输出:0
示例4:
输入:"()))(("
输出:4
提示:
S.length <= 1000
S只包含'('和')'字符。
思路:
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | class Solution: def minAddToMakeValid( self , S): """ :type S: str :rtype: int """ if S = = '': return 0 stack = [] right_kh_count = 0 left_kh_count = 0 for s in S: if s = = '(' : stack.append(s) elif s = = ')' and stack ! = []: stack.pop() else : left_kh_count + = 1 if stack ! = []: right_kh_count = len (stack) return left_kh_count + right_kh_count def minAddToMakeValid_leetcode( self , S): if S = = '': return 0 stack = [] for s in S: if s = = ')' and len (stack) > 0 and stack[ - 1 ] = = '(' : stack.pop() else : stack.append (s) return len (stack) s = Solution() num = s.minAddToMakeValid_leetcode(S = '())' ) print (num) |
2.下一个更大元素
Leetcode 496:下一个更大元素I
题目描述:给定两个没有重复元素的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。
说明:nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出-1。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 示例 1 : 输入: nums1 = [ 4 , 1 , 2 ], nums2 = [ 1 , 3 , 4 , 2 ]. 输出: [ - 1 , 3 , - 1 ] 解释: 对于num1中的数字 4 ,你无法在第二个数组中找到下一个更大的数字,因此输出 - 1 。 对于num1中的数字 1 ,第二个数组中数字 1 右边的下一个较大数字是 3 。 对于num1中的数字 2 ,第二个数组中没有下一个更大的数字,因此输出 - 1 。 <br>示例 2 : 输入: nums1 = [ 2 , 4 ], nums2 = [ 1 , 2 , 3 , 4 ]. 输出: [ 3 , - 1 ] 解释: 对于num1中的数字 2 ,第二个数组中的下一个较大数字是 3 。 对于num1中的数字 4 ,第二个数组中没有下一个更大的数字,因此输出 - 1 。 <br>注意: nums1和nums2中所有元素是唯一的。 nums1和nums2 的数组大小都不超过 1000 。 |
Leetcode 503:下一个更大元素II
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现