首页 > 其他分享 >LeetCode[150] 逆波兰表达式求值

LeetCode[150] 逆波兰表达式求值

时间:2022-09-26 19:55:22浏览次数:85  
标签:150 obj int stack tokens operand 求值 LeetCode 表达式

1 逆波兰表达式求值

1.1 题目描述

        根据逆波兰表示法,求表达式的值。有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

        注意:两个整数之间的除法只保留整数部分。可以保证给定的逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。

示例 1:
输入:tokens = [“2”,“1”,“+”,“3”,“*”]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9

示例 2:
输入:tokens = [“4”,“13”,“5”,“/”,“+”]
输出:6
解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6

示例 3:
输入:tokens = [“10”,“6”,“9”,“3”,“+”,“-11”,““,”/“,””,“17”,“+”,“5”,“+”]
输出:22
解释:该算式转化为常见的中缀算术表达式为:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5

        题目链接:https://leetcode.cn/problems/evaluate-reverse-polish-notation/

1.2 思路分析

        如(3+4)*5-6的逆波兰表达式为3 4 + 5 * 6 -
        1. 将表达式3 4 + 5 * 6 -放到List中(方便遍历)
        2. 将List传递给一个方法,用于计算
        3. 拿到List后,从左至右开始遍历,遇到数字直接压入栈
        4. 遇到运算符,弹出栈顶和次顶的元素,进行计算,将得到的结果再次放入栈中
        5. 一直重复,直到List遍历完毕,可得到最终结果

复杂度分析

  • 时间复杂度:\(O(n)\),其中\(n\)是数组tokens的长度。需要遍历数组tokens一次,计算逆波兰表达式的值。
  • 空间复杂度:\(O(n)\),其中\(n\)是数组tokens的长度。使用栈存储计算过程中的数,栈内元素个数不会超过逆波兰表达式的长度。

1.3 代码实现

        Python中的运算符函数:
方法一:

class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        operand_stack = []
        op_to_binary_fn = {
            "+": add,
            "-": sub,
            "*": mul,
            "/": lambda x, y: int(x / y)
        }       # 定义运算符              
        for token in tokens:
            try:
                num = int(token)
            except ValueError:
                operand2 = operand_stack.pop()
                operand1 = operand_stack.pop()
                num = op_to_binary_fn[token](operand1, operand2)
            finally:
                operand_stack.append(num)
        
        return operand_stack.pop()

方法二:

class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        operand_stack = []
        for token in tokens:
            try:
                num = int(token)
            except ValueError:
                operand2 = operand_stack.pop()
                operand1 = operand_stack.pop()
                num = self.doMatch(token, operand1, operand2)
            finally:
                operand_stack.append(num)
        
        return operand_stack.pop()

        
    def doMatch(self, op, op1, op2):        # 自定义运算规则
        if op == "*":
            return op1 * op2
        elif op == "/":
            return int(op1/op2)
        elif op == "+":
            return op1 + op2
        else:
            return op1 - op2

        看了其他人的解题思路,一般就是在运算符上操作不同,有的使用eval()函数。
解题心得:
问题一:
        Python 中没有一个函数可以判断一个字符串是否为合理的整数(包括正、负数)。str.isdigit()可以判断正数,但是无法判断负数。
        使用int()函数,并做try-except

  • 如果是整数,那么可以用int()转成数字;
  • 如果是运算符,那么int()会报错,从而进入 except中。

        整数字符串的最后一位肯定是数字,也可以以此来区分数字和运算符。

if token[-1].isdigit():
    stack.append(int(token))
else:
    pass    # 处理运算符

补充知识点:
operator 模块

运算

语法

函数

加法

a + b

add(a, b)

字符串拼接

seq1 + seq2

concat(seq1, seq2)

包含测试

obj in seq

contains(seq, obj)

除法

a / b

truediv(a, b)

除法

a // b

floordiv(a, b)

按位与

a & b

and_(a, b)

按位异或

a ^ b

xor(a, b)

按位取反

~ a

invert(a)

按位或

a | b

or_(a, b)

取幂

a ** b

pow(a, b)

标识

a is b

is_(a, b)

标识

a is not b

is_not(a, b)

索引赋值

obj[k] = v

setitem(obj, k, v)

索引删除

del obj[k]

delitem(obj, k)

索引取值

obj[k]

getitem(obj, k)

左移

a << b

lshift(a, b)

取模

a % b

mod(a, b)

乘法

a * b

mul(a, b)

矩阵乘法

a @ b

matmul(a, b)

取反(算术)

- a

neg(a)

取反(逻辑)

not a

not_(a)

正数

+ a

pos(a)

右移

a >> b

rshift(a, b)

切片赋值

seq[i:j] = values

setitem(seq, slice(i, j), values)

切片删除

del seq[i:j]

delitem(seq, slice(i, j))

切片取值

seq[i:j]

getitem(seq, slice(i, j))

字符串格式化

s % obj

mod(s, obj)

减法

a - b

sub(a, b)

真值测试

obj

truth(obj)

比较

a < b

lt(a, b)

比较

a <= b

le(a, b)

相等

a == b

eq(a, b)

不等

a != b

ne(a, b)

比较

a >= b

ge(a, b)

比较

a > b

gt(a, b)

标签:150,obj,int,stack,tokens,operand,求值,LeetCode,表达式
From: https://www.cnblogs.com/carpediem2021/p/16732041.html

相关文章

  • leetcode131-分割回文串 回溯与方便判断回文串的的判断表
    131.分割回文串这是看了卡尔的代码写出来的classSolution{public:intsize;vector<vector<string>>res;vector<string>path;boolisHuiwen(......
  • LeetCode42-接雨水
    inttrap(vector<int>&height){intres=0;intlen=(int)height.size();if(len<=1){returnres;}intl=0;intr=len......
  • [Oracle] LeetCode 32 Longest Valid Parentheses 思维
    Givenastringcontainingjustthecharacters'('and')',findthelengthofthelongestvalid(well-formed)parenthesessubstring.Solution不妨把左括号记为......
  • 好路径数目-Leetcode6191
    好路径数目题目描述给你一棵n个节点的树(连通无向无环的图),节点编号从0到n-1且恰好有n-1条边。给你一个长度为n下标从0开始的整数数组vals,分别表示每......
  • leetcode 208. Implement Trie (Prefix Tree) 实现 Trie (前缀树) (中等)
    一、题目大意Trie(发音类似"try")或者说前缀树是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。......
  • leetcode-简单1-8
    目录1.两数之和2.回文数3.罗马数字转整数4.最长公共前缀5.有效的括号6.最大同时在线人数7.无重复字符的最长子串8.链表删除倒数第n个节点1.两数之和/*题目:两数之和详细......
  • LeetCode腾讯精选50题 -- 三数之和
    题目:  分析:由题意,很容易看出可以三层循环,但是时间复杂度就为O(n^3)很容易运行超时,想办法进行简化(1)排序  要求三数相加为0 ,要是排序之后的数据都为正数,则必然不......
  • LeetCode 96 不同的二叉搜索树
    图解找递推公式constintN=20;classSolution{public:intdp[N];intnumTrees(intn){dp[0]=1;for(inti=1;i<=n;i++)......
  • LeetCode 700 二叉搜索树中的搜索
    二叉搜索树若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉搜......
  • [Oracle] LeetCode 76 Minimum Window Substring 双指针
    Giventwostringssandtoflengthsmandnrespectively,returntheminimumwindowsubstringofssuchthateverycharacterint(includingduplicates)isin......