一、题目:基本计算器【只有 + ,- ,以及括号】
实现一个基本的计算器来计算一个简单的字符串表达式的值。
字符串表达式可以包含左括号 (
,右括号 )
,加号 +
,减号 -
,非负整数和空格
。
示例 1:
输入: "1 + 1" 输出: 2
示例 2:
输入: " 2-1 + 2 " 输出: 3
示例 3:
输入: "(1+(4+5+2)-3)+(6+8)" 输出: 23
非递归思路:
栈:
采用栈存储遇到 ( 之前的结果。
遇到 ),将栈中最后一个数弹出计算结果。
处理过程:
res记录结果,stack用来存结果【遇到()先存前面的结果】,sign记录符号+、-
- 遇到 + :sign = 1
- 遇到 - :sign = -1
- 遇到数字:【考虑‘42’两个字母一起的情况,采用循环】结果 res += int (42) * sign
- 遇到 ’( ’:stack中加入 res和sign
- 遇到‘ ) ‘:stack弹出最后一个元素和倒数第二个元素来更新res
代码1:
def calculate(self, s): """ :type s: str :rtype: int """ if not s: return 0 #stack存储遇到括号(之前的计算结果res #temp记录数字,【如‘42’两个数字一起出现的情况】 #sign记录符号+,- #res记录计算结果 stack,temp = [],'' sign , res , i = 1 , 0 , 0 while i < len(s): #遇到字母:如果有两个数字同时出现,采用循环解决 #res结果把符号相乘 if s[i].isdigit(): while i<len(s) and s[i].isdigit(): temp += s[i] i += 1 i -= 1 res += int(temp)*sign #遇到+,-,sign=1,-1 elif s[i] == '+': sign = 1 elif s[i] == '-': sign = -1 #遇到(,将前面的res和符号sign存入栈中,初始化res和sign elif s[i] == '(': stack.append(res) stack.append(sign) res,sign = 0,1 #遇到),将栈中原来的结果res和符号sign弹出和当前的res更新得到新的结果res elif s[i] == ')': if stack: sign_tmp = stack.pop() res_tmp = stack.pop() res = res_tmp + res*sign_tmp i += 1 temp= '' return res
二、题目:基本计算器二【只有加减乘除,没有括号】
实现一个基本的计算器来计算一个简单的字符串表达式的值。
字符串表达式仅包含非负整数,+
, -
,*
,/
四种运算符和空格
。 整数除法仅保留整数部分。
示例 1:
输入: "3+2*2" 输出: 7
示例 2:
输入: " 3/2 " 输出: 1
示例 3:
输入: " 3+5 / 2 " 输出: 5
非递归思路1:
- 遇到数字:num存储
- 遇到符号:
- +:栈存储:+num
- -:栈存储:-num
- *:num = 栈弹出最后一个元素 * num,再存入栈中
- /:num = 栈弹出最后一个元素 / num,再存入栈中
如:'45/9',先num = 45,然后45前面默认为+ 符号,将45存入栈中,然后 sign = / ,num = 9,判断sign == '/',将45弹出与num==9相除。
即每个数字与其前面的符号相对应,sign和num。
代码1:
def calculate(self, s):
if not s:
return "0"
stack, num, sign = [], 0, "+"
for i in range(len(s)):
if s[i].isdigit():
num = num*10+ord(s[i])-ord("0")
if (not s[i].isdigit() and not s[i].isspace()) or i == len(s)-1:
if sign == "-":
stack.append(-num)
elif sign == "+":
stack.append(num)
elif sign == "*":
stack.append(stack.pop()*num)
else:
tmp = stack.pop()
if tmp//num < 0 and tmp%num != 0:
stack.append(tmp//num+1)
else:
stack.append(tmp//num)
sign = s[i]
num = 0
return sum(stack)
非递归思路2:
栈:
- 遇到数字:就将数字存入栈中。【考虑两个数字一起出现的情况】
- 遇到 * 或 / 就将乘或者除计算结束再存入栈中。【其中还要考虑是数字的情况】
- 将栈最后一个元素弹出,然后与 【乘号或者除号后面一个元素的数字】进行计算得到新的结果再存进栈中
- 遇到加减,sign = 1或-1
结果:
将栈中所有元素加总就可以了
代码2:
def calculate(self, s): """ :type s: str :rtype: int """ if not s: return 0 # return eval(s) stack = [] res,sign,i= 0,1,0 num = '' ca = True while i < len(s): ss = s[i] #数字,考虑两个数字出现的情况,用循环 if ss.isdigit(): while i<len(s) and s[i].isdigit(): num += s[i] i += 1 ca = False stack.append(int(num)*sign) #加减sign = 1或者-1 elif ss == '+': sign = 1 elif ss == '-': sign = -1 #乘号, elif ss == '*': #可能后面是空白符号 while not s[i].isdigit(): i += 1 #考虑两个数字一起出现 while i<len(s) and s[i].isdigit(): num += s[i] i += 1 ca = False #将栈最后一个元素和乘号*后面一个数字相乘 res = stack.pop() * int(num) #将结果存入栈中 stack.append(res) #除号 elif ss == '/': value = stack.pop() while not s[i].isdigit(): i += 1 while i<len(s) and s[i].isdigit(): num += s[i] i += 1 ca = False #m是用来限制除法取整的,如果除的结果是负数,则结果要加1,正数不用 m = value//int(num) if value % int(num) != 0: m += 1 if m < 0 else 0 #将除的结果加入栈中 res = int(m) stack.append(res) if ca: i += 1 num , ca = '',True return sum(stack)
三、题目:基本计算器三【既有乘除又有括号】
这道题将一和二结合,就是遇到括号就递归,别的就都与题目二一样。
思路:采用栈存储数字和加减符号,乘除在放入栈中已计算出结果。变量pre记录数字。括号就递归。
1、遇到数字:采用pre变量保存。
2、遇到符号:存入栈中,存入之前先把栈中的乘除结果算出来
3、遇到左括号:递归计算
4、遇到右括号:计算栈中的结果。
def getValue(s): if not s: return 0 return value(list(s),0)[0] #递归函数,遇到左括号 def value(arr,i): deque = [] pre = 0 while i < len(arr) and arr[i] != ')': #如果是数字,用pre变量保存 if arr[i].isdigit(): pre = pre * 10 + int(arr[i]) i += 1 #如果是符号,加入栈中,但先要把栈中的乘除结果算出来。 elif arr[i] != '(': mulNum(deque,pre) deque.append(arr[i]) i += 1 pre = 0 #如果是左括号(,就递归。 else: bra = value(arr,i+1) pre = bra[0] i = bra[1] + 1 #如果是右括号)或者结束了,就求出最终结果。 mulNum(deque,pre) return [addNum(deque),i] #乘除法计算 def mulNum(deque,pre): if deque: last = deque.pop() if last == '+' or last == '-': deque.append(last) else: cur = int(deque.pop()) pre = pre * cur if last == '*' else cur / pre deque.append(pre) #加减法计算 def addNum(deque): res = 0 sign = 1 while deque: cur = deque.pop(0) if cur == '-': sign = -1 elif cur == '+': sign = 1 else: res += sign * int(cur) return res exp = '48*((70-65)-43)+8*1*3+5/5' getValue(exp)