zoukankan      html  css  js  c++  java
  • 3. 数据结构---栈

    一、栈

    二、算法

    1.括号匹配

    Leetcode 20: 有效的括号

    题目描述:

    给定一个只包括 '('')''{''}''['']' 的字符串,判断字符串是否有效。

    有效字符串需满足:

    1. 左括号必须用相同类型的右括号闭合。
    2. 左括号必须以正确的顺序闭合。

    注意空字符串可被认为是有效字符串。

    示例:

    示例 1:
    输入: "()"
    输出: true
    
    示例 2:
    输入: "()[]{}"
    输出: true
    
    示例 3:
    输入: "(]"
    输出: false
    
    示例 4:
    输入: "([)]"
    输出: false
    
    示例 5:
    输入: "{[]}"
    输出: true  

    【思路】用栈保存括号的左半部分,遇到左半部分就入栈;遇到右半部分就查看栈顶元素是否与该括号为一对,如果是,就将栈顶元素出栈,否则,返回错误,表示该串括号无效。

    代码如下:

    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)

    代码如下:

    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代码:

    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代码:

    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只包含'('和')'字符。

    思路:

    代码如下:

    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:
    输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
    输出: [-1,3,-1]
    解释:
        对于num1中的数字4,你无法在第二个数组中找到下一个更大的数字,因此输出 -1。
        对于num1中的数字1,第二个数组中数字1右边的下一个较大数字是 3。
        对于num1中的数字2,第二个数组中没有下一个更大的数字,因此输出 -1。
    
    示例 2: 输入: nums1 = [2,4], nums2 = [1,2,3,4]. 输出: [3,-1] 解释: 对于num1中的数字2,第二个数组中的下一个较大数字是3。 对于num1中的数字4,第二个数组中没有下一个更大的数字,因此输出 -1。
    注意: nums1和nums2中所有元素是唯一的。 nums1和nums2 的数组大小都不超过1000。

      

    Leetcode 503:下一个更大元素II

    Leetcode 556:下一个更大元素III

  • 相关阅读:
    分享,如何激励程序员?
    [经验交流] (最新)移动App应用安全漏洞分析报告 !
    最全最热【资源汇总】Android应用解决方案全攻略
    最赚钱十大行业 网络编辑3G工程师入选
    分享:Android Studio 导入第三方jar包,重复加载错误解决办法。
    分享:怎么去测试一个 app 是否存在安全问题?
    Android系统刷机后第一次启动很慢的原因
    转载分享:Android APP二次打包操作步骤介绍
    Android开发之HelloWorld程序
    安卓源码总体结构(2)基础知识汇总
  • 原文地址:https://www.cnblogs.com/nxf-rabbit75/p/11815156.html
Copyright © 2011-2022 走看看