3. 數據結構---棧

1、棧

 

2、算法

1.括號匹配

Leetcode 20: 有效的括號

題目描述:python

給定一個只包括 '('')''{''}''['']' 的字符串,判斷字符串是否有效。算法

有效字符串需知足:數組

  1. 左括號必須用相同類型的右括號閉合。
  2. 左括號必須以正確的順序閉合。

注意空字符串可被認爲是有效字符串。app

示例:spa

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

【思路】用棧保存括號的左半部分,遇到左半部分就入棧;遇到右半部分就查看棧頂元素是否與該括號爲一對,若是是,就將棧頂元素出棧,不然,返回錯誤,表示該串括號無效。code

代碼以下:blog

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: 最長有效括號

題目描述:給定一個只包含 '(' 和 ')' 的字符串,找出最長的包含有效括號的子串的長度。遞歸

示例:leetcode

示例 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

相關文章
相關標籤/搜索