堆栈算法

堆栈算法

再讲算法之前先说一下堆与栈的区别
在这里插入图片描述
两个栈实现队列

# -*- coding:utf-8 -*-
class Solution:
    
    def __init__(self):
        self.stack1 = []
        self.stack2 = []
        
    def push(self, node):
        # write code here
        self.stack1.append(node)
    def pop(self):
        # return xx
        if self.stack2 == []:
            while self.stack1:
                self.stack2.append(self.stack1.pop())
        return self.stack2.pop()

包含min函数的栈

# -*- coding:utf-8 -*-
class Solution:
    def __init__(self):
        self.stack = []
        self.assit = []
    def push(self, node):
        # write code here
        min_data = self.min()
        if min_data > node or len(self.stack)==0:
            self.stack.append(node)
            self.assit.append(node)
        else:
            self.stack.append(node)
    def pop(self):
        # write code here
        if self.stack:
            if self.stack[-1] == self.assit[-1]:
                self.stack.pop()
                self.assit.pop()
            else:
                self.stack.pop()
    def top(self):
        # write code here
        if self.stack>0:
            return self.stack[-1]
    def min(self):
        # write code here
        if self.assit:
            return self.assit[-1]

栈的压入弹出

# -*- coding:utf-8 -*-
class Solution:
    def IsPopOrder(self, pushV, popV):
        # write code here
        stack = []
        while popV:
            if stack and stack[-1] == popV[0]:
                popV.pop(0)
                stack.pop()
            elif pushV :
                stack.append(pushV.pop(0))
            else:
                return False
        return True
            

滑动窗口的最大值(queue中保存的是滑动窗口最大值的下标)

# -*- coding:utf-8 -*-
class Solution:
    def maxInWindows(self, num, size):
        # write code here
        queue,res,i = [],[],0
        while size>0 and i<len(num):
            if len(queue)>0 and i-size+1>queue[0]:
                queue.pop(0)
            while len(queue)>0 and num[queue[-1]] < num[i]:
                queue.pop()
            queue.append(i)
            if i>=size-1:
                res.append(num[queue[0]])
            i +=1
        return res

电话号码的字母组合:

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        if not digits:
            return []
        d = [" ","*","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"]
        res = ['']
        
        for i in digits:
            letter = d[ord(i)-48]
            size = len(res)
            for _ in range(size):
                tmp = res.pop(0)
                for j in letter:
                    res.append(tmp+j)
        return res

有效的括号:

class Solution:
    def isValid(self, s: str) -> bool:
        if not s:
            return True
        dict = {'(':')','[':']','{':'}','?':'?'}
        stack = ['?']
        for i in s:
            if i in dict:
                stack.append(i)
            elif dict[stack.pop()] !=i :
                return False
        return len(stack)==1

接雨水:

class Solution:
    def trap(self, height: List[int]) -> int:
        length = len(height)
        if length < 3: return 0
        res, idx = 0, 0
        stack = []
        while idx < length:
            while len(stack) > 0 and height[idx] > height[stack[-1]]:
                top = stack.pop()  # index of the last element in the stack
                if len(stack) == 0:
                    break
                h = min(height[stack[-1]], height[idx]) - height[top]
                dist = idx - stack[-1] - 1
                res += (dist * h)
            stack.append(idx)
            idx += 1
        return res

简化路径

class Solution:
    def simplifyPath(self, path: str) -> str:
        stack = []
        path = path.split('/')
        for i in path:
            if i == '..':
                if stack:
                    stack.pop()
            elif i and i !='.':
                stack.append(i)
        return '/'+'/'.join(stack)

柱形图中最大的矩形

class Solution:
    def largestRectangleArea(self, heights: List[int]) -> int:
        n = len(heights)
        res = 0
        stack = [0]
        height = [0] + heights + [0]

        for i in range(1,n+2):
            while stack and height[i]<height[stack[-1]]:
                h = height[stack.pop()]
                if not stack:
                    break
                w = i - stack[-1] -1
                res = max(res,h*w)
            stack.append(i)
        return res

逆波兰表达式求值

class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        f = ['+','-','*','/']
        stack = []
        res = 0
        if len(tokens)==1:
            return int(tokens[0])
        for i in tokens:
            if i not in f:
                stack.append(i)
            elif i == '+':
                right = int(stack.pop())
                left = int(stack.pop())
                res = left + right
                stack.append(res)
            elif i == '-':
                right = int(stack.pop())
                left = int(stack.pop())
                res = left - right
                stack.append(res)
            elif i == '*':
                right = int(stack.pop())
                left = int(stack.pop())
                res = left * right
                stack.append(res)
            else:
                right = int(stack.pop())
                left = int(stack.pop())
                res = left / right
                stack.append(res)
        return int(res)

最小栈

class MinStack:

    def __init__(self):
        """
        initialize your data structure here.
        """
        self.stack = []
    def push(self, x: int) -> None:
        return self.stack.append(x)
    def pop(self) -> None:
        return self.stack.pop()
    def top(self) -> int:
        return self.stack[-1]
    def getMin(self) -> int:
        return min(self.stack)

数组中第K个最大的元素

#最大堆

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        
        把最大的元素放在数组的头部
        def adjust_heap(idx, max_len):
            left = 2 * idx + 1
            right = 2 * idx + 2
            max_loc = idx
            if left < max_len and nums[max_loc] < nums[left]:
                max_loc = left
            if right < max_len and nums[max_loc] < nums[right]:
                max_loc = right
            if max_loc != idx:
                nums[idx], nums[max_loc] = nums[max_loc], nums[idx]
                adjust_heap(max_loc, max_len)
        
        # 建堆
        n = len(nums)
        for i in range(n // 2 - 1, -1, -1):
            adjust_heap(i, n)
        #print(nums)
        res = None
        for i in range(1, k + 1):
            #print(nums)
            res = nums[0]
            nums[0], nums[-i] = nums[-i], nums[0]
            adjust_heap(0, n - i)
        return res
        
#快排

class Solution:
    def findKthLargest(self, nums: List[int], k: int) -> int:
        def partition(left, right):
            pivot = nums[left]
            l = left + 1
            r = right
            while l <= r:
                if nums[l] < pivot and nums[r] > pivot:
                    nums[l], nums[r] = nums[r], nums[l]
                if nums[l] >= pivot:
                    l += 1
                if nums[r] <= pivot:
                    r -= 1
            nums[r], nums[left] = nums[left], nums[r]
            return r
        left = 0
        right = len(nums) - 1
        while 1:
            idx = partition(left, right)
            if idx == k - 1:
                return nums[idx]
            if idx < k - 1:
                left = idx + 1
            if idx > k - 1:
                right = idx - 1

基本计数器

class Solution:
    def calculate(self, s: str) -> int:
        stack = []
        # 记录数字的符号, 因为题目说没有负数,说明第一个为正数,设为1
        sign = 1
        # 数字
        num = 0
        # 结果
        res = 0
        for c in s:
            if c.isdigit():
                num = num * 10 + int(c)
            elif c == "+":
                res += sign * num
                # 为下一次做准备
                num = 0
                sign = 1
            elif c == "-":
                res += sign * num
                # 为下一次做准备
                num = 0
                sign = -1
            elif c == "(":
                stack.append(res)
                stack.append(sign)
                sign = 1
                res = 0
            elif c == ")":
                res += sign * num
                num = 0
                res = stack.pop() * res + stack.pop()
        res += sign * num
        return res

删除无效的括号

class Solution:
    def removeInvalidParentheses(self, s:str) -> List[str]:
        def isValid(s:str)->bool:
            cnt = 0
            for c in s:
                if c == "(": cnt += 1
                elif c == ")": cnt -= 1
                if cnt < 0: return False  # 只用中途cnt出现了负值,你就要终止循环,已经出现非法字符了
            return cnt == 0

        # BFS
        level = {s}  # 用set避免重复
        while True:
            valid = list(filter(isValid, level))  # 所有合法字符都筛选出来
            if valid: return valid # 如果当前valid是非空的,说明已经有合法的产生了
            # 下一层level
            next_level = set()
            for item in level:
                for i in range(len(item)):
                    if item[i] in "()":                     # 如果item[i]这个char是个括号就删了,如果不是括号就留着
                        next_level.add(item[:i]+item[i+1:])
            level = next_level

计算右侧小于当前元素的个数

import bisect
class Solution:
    def countSmaller(self, nums: List[int]) -> List[int]:
        re_nums = nums[::-1]
        bi_arr = []
        res = []
        for _ in re_nums:
            #插入_数字时在数组中的位置
            pos = bisect.bisect_left(bi_arr, _)
            res.append(pos)
            #插入_
            bisect.insort_left(bi_arr, _)
        return res[::-1]

根据身高重建队列

class Solution:
    def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
        people.sort(key = lambda x: (-x[0], x[1]))
        output = []
        for p in people:
            output.insert(p[1], p)
        return output

下一个更大的元素

class Solution:
    def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
        stack, hashmap = list(), dict()
        for i in nums2:
            while len(stack) != 0 and stack[-1] < i:
                hashmap[stack.pop()] = i
            stack.append(i)
        return [hashmap.get(i,-1) for i in nums1]

每日温度

import collections
class Solution:
    def dailyTemperatures(self, T: List[int]) -> List[int]:
        n = len(T)
        ans = [0]*n
        stack = []
        for i in range(n-1,-1,-1):
            while stack and T[i]>=T[stack[-1]]:
                stack.pop()
            #stack里面保存的永远都是从大到小的温度的index
            #stack[-1]是T[i]<的最近的index
            #因为是倒序遍历,所以不用考虑stack.pop()出的温度,
            # 因为他的index值大于stack[-1]的index,但是温度却小于stack[-1]的温度,
            # 通俗的说就是性价比较低
            if stack:
                ans[i] = stack[-1]-i
            stack.append(i)
        return ans
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值