这次记录的两题是这两天做的每日一题的题目,正好这两题是同一个系列的,所以放到一起记下来。先看一下第一题的题目描述。
地址:基本计算器一
题目很好理解,就是让我们实现计算字符串形式的数学表达式。主要需要关注提示中的内容,提示告诉我们s中只包含加减运算,另外还需要考虑括号对计算顺序的影响,没有涉及到乘除法运算。那么我们看到这个题目,首先想到的肯定应该是使用栈来解决。那么看一下如何用栈来解答这道题吧。
解法一
既然题目说了只有加减法,那么我们就只考虑加减法,我们可以设置一个标记,用来表示加减法,标记的值为+1和-1,在将栈中元素相加时,先与标记相乘,以此来表示加减法。
遇到左括号时将当前结果以及标记入栈入栈,遇到右括号就出栈计算。
class Solution(object):
def calculate(self, s):
res, num, sign = 0, 0, 1
stack = []
for c in s:
if c.isdigit():
num = 10 * num + int(c)
elif c == "+" or c == "-":
res += sign * num
num = 0
sign = 1 if c == "+" else -1
elif c == "(":
stack.append(res)
stack.append(sign)
res = 0
sign = 1
elif c == ")":
res += sign * num
num = 0
res *= stack.pop()
res += stack.pop()
res += sign * num
return res
代码有些不太好理解,如果看不懂的话可以调试一下看看,观察每一步各个变量都是如何改变的,都有什么作用。多试几个测试样例就理解了。
这里还有一个小细节,题目中并没有说数字都是各位数。如果数字不是个位数的话,我们就需要做一些处理,可以看到代码前面用了一个num来计算数字的值。
下面来看一下基本计算器二的题目。
地址:基本计算器二
这一题跟上一题相比增加了乘除法,但是减少了括号,从难度上来说,反而比上一题更简单一些了。解决方法还是使用栈。
解法一
与上题类似,还是需要设置一个标记,但是这个标记不是+1和-1,而是加减乘除的符号。标价中存的是当前元素的上一个符号,然后根据这个上一个符号来决定如何操作当前元素。因为不包含括号,所以我们直接从前往后遍历就可以了,遇到乘除就把栈顶元素弹出先计算,然后再将结果放入栈中。最后将栈内所有元素加起来就可以了。
class Solution:
def calculate(self, s: str) -> int:
stack = []
nums = 0
presign = '+'
n=len(s)
for i in range(n):
if s[i].isdigit():
nums = nums*10 + int(s[i])
if not s[i].isdigit() and s[i] != ' ' or i == n-1:
if presign == '+':
stack.append(nums)
elif presign == '-':
stack.append(-nums)
elif presign == '*':
stack.append(stack.pop()*nums)
elif presign == '/':
t = stack.pop()
if t<0:
stack.append(-(-t//nums))
else:
stack.append(t//nums)
nums = 0
presign = s[i]
res = 0
for i in stack:
res = res+i
return res
官方解答没有给出python版本,这是我根据java版重写的。里面有一点比较诡异的地方就是计算除法时需要做一个判断。因为python的//号取商是向下取整,并不是只保留整数部分,因此当数据为负数时可能会出现向下取整后比当前整数部分小1的情况,所以我这里就直接改成正数计算完之后再转回负数。其他的地方都是正常的思路。
这两题主要用到的方法是栈,但是我感觉还是有点难度的,特别是第一题,需要逻辑十分清晰才能看懂过程。