python-数据结构与算法分析-基本数据结构-栈

线性数据结构

线性数据结构:栈、队列、双端队列和列表都是有序的数据集合,其元素的顺序取决于添加顺序或移除顺序。一旦某个元素被添加进来,它与前后元素的相对位置将保持不变。

满足last-in-first-out,包含以下函数:

  • Stack() 创建一个空栈
  • push(item) 将一个元素添加到栈顶端
  • pop() 移除栈顶元素,并返回值
  • peek() 返回栈顶元素
  • isEmpty() 检查是否为空,返回bool
  • size() 返回栈中元素的数目
class Stack:
    def __init__(self):
        self.items = []

    def isEmpty(self):
        return self.items == []

    def push(self, item):
        self.items.append(item)

    def pop(self):
        return self.items.pop()

    def peek(self):
        return self.items[-1]

    def size(self):
        return len(self.items)

if __name__ == "__main__":
    s = Stack()
    s.push(12)
    s.push('hello')
    print(s.size())
    print(s.pop())
    print(s.size())

案例:括号匹配(不写了)

中序、前序、后序表达式
前后中指的是运算符的位置。在写前序时,先写运算符,再写左右两个操作数。如果有括号,先把括号里面的改成表达式,然后作为一个整体继续写表达式。如下表所示,前序和后序表达式并不需要括号,运算顺序就是包含在表达式的书写顺序里的。

中序表达式前序表达式后序表达式
A + B+ A BA B +
A + B * C+ A * B CA B C * +
(A + B) * C* + A B CA B + C *

在这里插入图片描述

以下基于这个假设:假设后序表达式是一个以空格分隔的字符串,运算符有±/,操作数是一位整数值*

中序转后序
算法:

  1. ans保存结果,op_stack保存运算符,prec保存各运算符的优先级
  2. 从左到右扫描表达式:当前字符为token
    • 如果token是操作数,则添加到ans
    • 如果token是(,则压入op_stack
    • 如果token是),则反复从op_stack中pop元素添加到ans,直到遇到(
    • 如果是运算符,要先从op_stack中取出优先级更高或相同的运算符,添加到ans,然后将token压入op_stack
  3. 如果此时op_stack不是空栈,则依次出栈添加到ans末尾
import string

def infixToPostfix(infix_expr):
    prec = {'*':3, '/':3, '+':2, '-':2, '(':1}
    op_stack = Stack() # 使用前面的Stack
    ans = []
    # 将表达式转为list
    tokens = list(infix_expr.replace(' ', ''))
    for token in tokens:
        # 如果是操作数
        if token in string.digits:
            ans.append(token)
        elif token == '(': 
            op_stack.push(token)
        elif token == ')':
            top_token = op_stack.pop()
            while top_token != '(':
                ans.append(top_token)
                top_token = op_stack.pop() # 最后一个(也会被pop出去
        else:
            while (not op_stack.isEmpty()) and (prec[op_stack.peek()] >= prec[token]):
                ans.append(op_stack.pop())
            op_stack.push(token)
    # 剩余的压入ans
    while not op_stack.isEmpty():
        ans.append(op_stack.pop())
    return " ".join(ans)

if __name__ == "__main__":
    print(infixToPostfix("(1+2)*(3+4)")) # 1 2 + 3 4 + *
    print(infixToPostfix("5 + 6 * 7")) # 5 6 7 * +

计算后序表达式的值

  1. ans保存结果,op_stack保存操作数
  2. 从左到右扫描表达式:
    • 如果是数字,转换为整数并压入op_stack
    • 如果是运算符,从op_stack中pop栈顶两个元素,计算,然后将运算结果压入op_stack
  3. ans中的值是结果,返回即可
def postfixEval(postfix_expr):
    op_stack = Stack()
    tokens = postfix_expr.split()
    for token in tokens:
        if token in string.digits:
            op_stack.push(token)
        else:
            op1 = op_stack.pop()
            op2 = op_stack.pop()
            op_stack.push(str(eval(op2 + token + op1)))
    return op_stack.pop()

if __name__ == "__main__":
	print(postfixEval(infixToPostfix("1 + 3*5"))) # 16

496. 下一个更大元素 I

https://leetcode.cn/problems/next-greater-element-i

nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x 大的元素。

给你两个 没有重复元素 的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集。

对于每个 0 <= i < nums1.length ,找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j] 的 下一个更大元素 。如果不存在下一个更大元素,那么本次查询的答案是 -1 。

返回一个长度为 nums1.length 的数组 ans 作为答案,满足 ans[i] 是如上所述的 下一个更大元素 。

示例 1:
输入:nums1 = [4,1,2], nums2 = [1,3,4,2].
输出:[-1,3,-1]
解释:nums1 中每个值的下一个更大元素如下所述:

  • 4 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
  • 1 ,用加粗斜体标识,nums2 = [1,3,4,2]。下一个更大元素是 3 。
  • 2 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。

思路:
先计算nums2的下一个更大元素字典,再用nums1直接查找即可。计算下一个更大元素字典时,使用list实现栈,原则是:弹出比当前元素小的元素,如果一个元素比当前元素大,那么它就是下一个更大元素。如果栈里没有元素了,说明找不到。从数组后面向前这样操作即可。

class Solution:
    def getNextMax(self, nums):
        arr = []
        ans = []
        for i in range(len(nums) - 1, -1, -1):
            while len(arr) != 0 and arr[-1] <= nums[i]:
                arr.pop()
            if len(arr) == 0:
                ans.append(-1)
            else:
                ans.append(arr[-1])
            arr.append(nums[i])
        return ans[::-1]

    def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
        res = self.getNextMax(nums2)
        d = {}
        for i in range(len(nums2)):
            d[nums2[i]] = res[i]
        ans = []
        for n in nums1:
            ans.append(d[n])
        return ans

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值