Leetcode 棧知識點總結

來看下Leetcode中Tag爲Stack的題目

  • [Leetcode 739] Daily Temperatures:求下一個溫暖天氣距離當前日期的時間差。Medium
class Solution(object):
    def dailyTemperatures(self, temperatures):
        """
        :type temperatures: List[int]
        :rtype: List[int]
        """
        size,stack = len(temperatures),[]
        ret = [0]*size
        for idx,tem in enumerate(temperatures):
            while(stack and temperatures[stack[-1]]<tem):
                idj = stack.pop()
                ret[idj]=idx-idj
            stack.append(idx)
        return ret
  • [Leetcode 496] Next Greater Element I:給定兩個數組(無重複)nums1 與 nums2,其中nums1的元素是nums2的子集。在nums2中尋找大於nums1中對應位置且距離最近的元素。如果對應位置不存在這樣的元素,則輸出-1。Easy
    思路:用stack維護一個遞減序列,當num>stack[-1] 時 彈出stack[-1]同時表示num是彈出的值的下一個大元素
class Solution(object):
    def nextGreaterElement(self, findNums, nums):
        """
        :type findNums: List[int]
        :type nums: List[int]
        :rtype: List[int]
        """
        dmap,stack = {},[]
        for num in nums:
            while stack and stack[-1]<num:
                dmap[stack.pop()]=num
            stack.append(num)
        return [dmap.get(n,-1) for n in findNums]
  • [Leetcode 503] Next Greater Element II:求循環數組的最近較大值。Medium
    思路:其實和前一題一樣,因爲是循環數組,對數組進行拼接再操作即可
class Solution(object):
    def nextGreaterElements(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        size,stack = len(nums),[]
        ret = [-1]*size
        nums = nums+nums
        for idx,num in enumerate(nums):
            while stack and nums[stack[-1]]<num:
                idj = stack.pop()
                if idj<size: ret[idj]=num
            stack.append(idx)
        return ret
  • [Leetcode 682] Baseball Game:一個數組,數字字符表示當局得分,’C’表示上一局得分無效,’D’表示上一局得分翻倍,‘+’表示得分前兩局之和,求總的分數,Easy
class Solution(object):
    def calPoints(self, ops):
        """
        :type ops: List[str]
        :rtype: int
        """
        stack = []
        for op in ops:
            if op=='C':
                stack.pop()
            elif op=='D':
                stack.append(stack[-1]*2)
            elif op=='+':
                stack.append(stack[-1]+stack[-2])
            else:
                stack.append(int(op))
        return sum(stack)
  • [Leetcode 735] Asteroid Collision:行星碰撞問題。+,-表示方向,大小表示質量,若發生碰撞,則保留大質量的行星,若兩行星質量相同,則一起消失。Medium
class Solution(object):
    def asteroidCollision(self, asteroids):
        """
        :type asteroids: List[int]
        :rtype: List[int]
        """
        stack = []
        for asteroid in asteroids:
            flag = True
            while(stack and stack[-1]>0 and asteroid<0 and flag):
                if -asteroid>stack[-1]: stack.pop()
                else:
                    flag = False
                    if -asteroid==stack[-1]: stack.pop()
            if flag:  stack.append(asteroid)
        return stack
  • [Leetcode 636] Exclusive Time of Functions:給定一組函數調用日誌,格式爲”function_id:start_or_end:timestamp”,函數可以遞歸。求每個函數調用的總時長。Medium
    思路:這題其實巧妙在棧頂元素的變化。如果有新的函數進來,可以先計算stack[-1] 的調用時間,如果當前函數執行完畢,trick在stack[-1][1] = logtime+1,即記錄成當前stack[-1]重新執行的時間
class Solution(object):
    def exclusiveTime(self, n, logs):
        """
        :type n: int
        :type logs: List[str]
        :rtype: List[int]
        """
        stack,ans = [],[0 for i in range(n)]
        for log in logs:
            logname,state,logtime = log.split(':')
            logname,logtime = int(logname),int(logtime)
            if state == 'start':
                if len(stack):
                    ans[stack[-1][0]]+=logtime-stack[-1][1]
                stack.append([logname,logtime])
            else:
                lastitem = stack.pop()
                ans[lastitem[0]]+=logtime-lastitem[1]+1
                if len(stack):
                    stack[-1][1]=logtime+1
        return ans
class MyQueue(object):
    def __init__(self):
        self.stack1 = []
        self.stack2 = []
    def push(self, node):
        self.stack1.append(node)
    def pop(self):
        if len(self.stack2):
            return self.stack2.pop()
        while(self.stack1):
            self.stack2.append(self.stack1.pop())
        return self.stack2.pop()
    def peek(self):
        if len(self.stack2):
            return self.stack2[-1]
        while(self.stack1):
            self.stack2.append(self.stack1.pop())
        return self.stack2[-1]
    def empty(self):
        return self.stack1==[] and self.stack2==[]
  • [Leetcode 225] Implement Stack using Queues:用隊列數據結構來實現棧, Easy
    思路:主要是要注意到隊列是先進先出,而棧是先進後出,那麼top和pop操作在隊列中的應用可以看成是把對首的元素加入到隊尾的過程。
class MyStack(object):

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.queue = []
        self.size = 0
    def push(self, x):
        """
        Push element x onto stack.
        :type x: int
        :rtype: void
        """
        self.queue.append(x)
        self.size +=1
    def pop(self):
        """
        Removes the element on top of the stack and returns that element.
        :rtype: int
        """
        for i in range(self.size-1):
            self.queue.append(self.queue.pop(0))
        self.size -=1
        return self.queue.pop(0)
    def top(self):
        """
        Get the top element.
        :rtype: int
        """
        for i in range(self.size-1):
            self.queue.append(self.queue.pop(0))
        target = self.queue.pop(0)
        self.queue.append(target)
        return target
    def empty(self):
        """
        Returns whether the stack is empty.
        :rtype: bool
        """
        return self.size == 0
  • [Leetcode 155] Min Stack:設計一個最小棧,劍指原題.Easy
class MinStack(object):
    def __init__(self):
        """
        initialize your data structure here.
        """
        self.stack = []
        self.minstack =[]
    def push(self, x):
        """
        :type x: int
        :rtype: void
        """
        self.stack.append(x)
        if len(self.minstack)==0 or self.minstack[-1][0]>x:
            self.minstack.append((x,1))
        elif self.minstack[-1][0] == x:
            self.minstack[-1] = (x,self.minstack[-1][1]+1)

    def pop(self):
        """
        :rtype: void
        """
        ans = self.stack[-1]
        self.stack = self.stack[0:len(self.stack)-1]
        if ans == self.minstack[-1][0]:
            if self.minstack[-1][1] == 1:
                self.minstack.remove(self.minstack[-1])
            else:
                self.minstack[-1] = (ans,self.minstack[-1][1]-1)
    def top(self):
        """
        :rtype: int
        """
        return self.stack[-1]
    def getMin(self):
        """
        :rtype: int
        """
        return self.minstack[-1][0]
class Solution(object):
    def inorderTraversal(self,root): # iterative
        '''
        :param root: TreeNode
        :return: List[int]
        '''
        stack,ret = [],[]
        if root == None: return []
        stack.append(root)
        while(stack):
            query = stack.pop()
            if query.left == None and query.right == None:
                ret.append(query.val)
            else:
                if query.right:
                    stack.append(query.right)
                stack.append(TreeNode(query.val))
                if query.left:
                    stack.append(query.left)
        return ret

上述的空間複雜度是O(size),拍腦袋(其實是看別人的博客啦·)想到一個O(k)k是樹深的想法,維護一個棧,從根節點開始,每次迭代地將根節點的左孩子壓入棧,直到左孩子爲空爲止。調用next()方法時,彈出棧頂,如果被彈出的元素擁有右孩子,則以右孩子爲根,將其左孩子迭代壓棧。書影博客

class Solution(object):
    def inorderTraversal(self,root): # iterative
        '''
        :param root: TreeNode
        :return: List[int]
        '''
        stack,ret = [],[]
        if root is None: return []
        stack.append(root)
        while(root):
            if root.left:
                stack.append(root.left)
            root = root.left
        while(stack):
            root = stack.pop()
            ret.append(root.val)
            root = root.right
            while(root):
                stack.append(root)
                root = root.left
        return ret
  • [Leetcode 144] Binary Tree Preorder Traversal:求二叉樹的先序遍歷結果。Medium
    思路:先序遍歷結果爲VLR,那麼壓棧順序爲[RL]然後展開
class Solution(object):
    def preorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        if root == None:
            return []
        ret = []
        stack = [root]
        while(len(stack)):
            query = stack.pop()
            ret.append(query.val)
            if query.right:
                stack.append(query.right)
            if query.left:
                stack.append(query.left)
        return ret
  • [Leetcode 145] Binary Tree Postorder Traversal:求二叉樹的後序遍歷結果。Medium
    思路:後序遍歷結果爲LRV,那麼壓棧順序爲[VRL]然後展開
class Solution(object):
    def postorderTraversal(self, root):
        """
        :type root: TreeNode
        :rtype: List[int]
        """
        ret = []
        if root == None:
            return ret
        stack  = [root]
        while(len(stack)):
            query = stack.pop()
            if query.left == None and query.right == None:
                ret.append(query.val)
            else:
                stack.append(TreeNode(query.val))
                if query.right:
                    stack.append(query.right)
                if query.left:
                    stack.append(query.left)
        return ret
class Solution(object):
    def zigzagLevelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        ret, stack, step = [], [], 0
        if root == None: return ret
        stack.append(root)
        while (stack):
            tmpstack = []
            tmp = []
            for node in stack:
                tmp.append(node.val)
                if node.left:
                    tmpstack.append(node.left)
                if node.right:
                    tmpstack.append(node.right)
            if step % 2:
                tmp = tmp[::-1]
            ret.append(tmp[:])
            step += 1
            stack = tmpstack[:]
        return ret
class Solution(object):
    def evalRPN(self, tokens):
        """
        :type tokens: List[str]
        :rtype: int
        """
        stack = []
        for token in tokens:
            if token in ['+','-','*','/']:
                num1 = stack.pop()
                num2 = stack.pop()
                if token=='+': 
                    stack.append(num1+num2)
                elif token == '-':
                    stack.append(num2-num1)
                elif token == '*':
                    stack.append(num1*num2)
                else:
                    if num1*num2<0:
                        ans = -(-num2/num1)
                    else:
                        ans = num2/num1
                    stack.append(ans)
            else:
                stack.append(int(token))
        return stack[0] 
  • [Leetcode 331] Verify Preorder Serialization of a Binary Tree:判斷一個字符串是否是某個二叉樹的先序遍歷序列化格式,Medium
    思考:用一個stack維護當前結點的狀態 0:結點左右孩子結點格式未滿足,1:結點的右孩子結點格式已滿足 2:結點的左右結點格式已滿足,這時候需要pop,同時把stack[-1]+=1
class Solution(object):
    def isValidSerialization(self, preorder):
        """
        :type preorder: str
        :rtype: bool
        """
        order = preorder.split(',')
        if order == [] or order == ['#']: return True
        stack,flag = [],True
        for token in order:
            if token == '#':
                if stack == []: return False
                stack[-1]+=1
                while(stack and stack[-1]==2):
                    stack.pop()
                    if stack: stack[-1]+=1
            else:
                if stack == []:
                    if flag: 
                        stack = [0]
                        flag = False
                    else:
                        return False
                else:
                    stack.append(0)
        return stack == []
class Solution(object):
    def simplifyPath(self, path):
        """
        :type path: str
        :rtype: str
        """
        path_array = path.split('/')
        stack = []
        for item in path_array:
            if item not in ['','.','..']:
                stack.append(item)
            elif item == '..' and len(stack):
                stack.pop(-1)
        if stack ==[]:
            return '/'
        else:
            return '/'+'/'.join(stack)
class Solution(object):
    def isValid(self, s):
        """
        :type s: str
        :rtype: bool
        """
        stack = []
        dic = {')':'(',']':'[','}':'{'}
        for i in s:
            if i in ['(','[','{']:
                stack.append(i)
            elif i in [')',']','}']:
                if len(stack) and stack[-1]==dic[i]:
                    stack.pop()
                else:
                    return False
            else:
                return False
        if len(stack)==0:
            return True
        return False
  • [Leetcode 341] Flatten Nested List Iterator:給定一個嵌套的整數列表,實現一個迭代器將其展開。每一個元素或者是一個整數,或者是一個列表 – 其元素也是一個整數或者其他列表。Medium
class NestedIterator(object):

    def __init__(self, nestedList):
        """
        Initialize your data structure here.
        :type nestedList: List[NestedInteger]
        """

        def getList(query):
            query=query.getList()
            ans = []
            for i in range(len(query)):
                if query[i].isInteger():
                    ans += [query[i]]
                else:
                    ans += getList(query[i])
            return ans
        self.stack = []
        for i in range(len(nestedList)):
            if nestedList[i].isInteger():
                self.stack += [nestedList[i]]
            else:
                self.stack += getList(nestedList[i])

    def next(self):
        """
        :rtype: int
        """
        ret = self.stack.pop(0)
        return ret.getInteger()
    def hasNext(self):
        """
        :rtype: bool
        """
        return self.stack !=[]
  • [Leetcode 456] 132 Pattern:判斷數組中是否包含132形式,Medium
class Solution(object):
    def find132pattern(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        size,third,stack =len(nums),None,[]
        for i in range(size):
            num = nums[size-1-i]
            if third and num < third:
                return True
            else:
                while(len(stack) and num>stack[-1]):
                    third = stack[-1]
                    stack.pop()
            stack.append(num)
        return False
  • [Leetcode 402] Remove K Digits:從字符串中移除k個字符,使得剩下的字符組成的數字最小,Medium
    思路:stack[-1]>num時移除,同時k–
class Solution(object):
    def removeKdigits(self, num, k):
        """
        :type num: str
        :type k: int
        :rtype: str
        """
        stack = []
        length = len(num)-k
        for i in num:
            while len(stack) and k>0 and stack[-1]>i:
                stack.pop()
                k-=1
            stack.append(i)
        ret = ''
        flag = True
        for i in range(length):
            if flag:
                if stack[i]!='0':
                    ret+=stack[i]
                    flag =False
            else:
                ret +=stack[i]
        if len(ret)==0:
            return '0'
        return ret
class Solution(object):
    def decodeString(self, s):
        """
        :type s: str
        :rtype: str
        """
        digit = None
        stack = []
        for si in s:
            if si>='0' and si<='9':
                if digit==None:
                    digit=int(si)
                else:
                    digit=digit*10+int(si)
            elif si=='[':
                if digit!=None:
                    stack.append(digit)
                    digit=None
                stack.append(si)
            elif si==']':
                tmp = ''
                while(stack and stack[-1]!='['):
                    tmp = stack[-1]+tmp
                    stack.pop()
                stack[-1] = tmp
                if len(stack)>1 and isinstance(stack[-2],int):
                    stack[-2] = stack[-2]*stack[-1]
                stack.pop()
            else:
                stack.append(si)
        return ''.join(stack)
class Solution(object):
    def deserialize(self, s):
        """
        :type s: str
        :rtype: NestedInteger
        """
        stack = []
        sigma, negmul = None, 1
        for c in s:
            if c == '-':
                negmul = -1
            elif '0' <= c <= '9':
                sigma = (sigma or 0) * 10 + int(c)
            elif c == '[':
                stack.append(NestedInteger())
            else:
                if sigma is not None:
                    stack[-1].add(NestedInteger(sigma * negmul))
                    sigma, negmul = None, 1
                if c == ']':
                    top = stack.pop()
                    if stack: stack[-1].add(top)
                    else: return top
        return NestedInteger((sigma or 0) * negmul)
  • [Leetcode 726] Number of Atoms:將分子式展開,返回各原子的個數,Hard
    思路:字符串處理,分情況討論
import collections
class Solution(object):
    def countOfAtoms(self, formula):
        """
        :type formula: str
        :rtype: str
        """
        size = len(formula)
        def getDigit(idx):
            cnt = 0
            while (idx < len(formula) and formula[idx].isdigit()):
                cnt = cnt*10+int(formula[idx])
                idx += 1
            idx-=1
            if cnt:
                return cnt,idx
            else:
                return 1,idx

        stack = [collections.defaultdict(int)]
        idx = 0
        while(idx<len(formula)):
            token = formula[idx]
            if token>='A' and token<='Z':
                ch = token
                idx+=1
                while (idx < len(formula) and formula[idx]>='a' and formula[idx]<='z'):
                    ch+=formula[idx]
                    idx += 1
                cnt,idx = getDigit(idx)
                stack[-1][ch]=stack[-1][ch]+cnt 
            elif token=='(':
                stack.append(collections.defaultdict(int))
            elif token==')':
                idx +=1
                cnt,idx = getDigit(idx)
                for key in stack[-1]:
                    stack[-1][key] = stack[-1][key]*cnt
                tstack = stack.pop()
                for key in tstack:
                    stack[-1][key]+=tstack[key]
            idx+=1

        ret = ''
        for x in sorted(stack[-1].items(),key=lambda x:x[0]):
            if x[1]!=1:
                ret+=x[0]+str(x[1])
            else:
                ret+=x[0]
        return ret
發佈了196 篇原創文章 · 獲贊 73 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章