题目:

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。

整数除法仅保留整数部分。

你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1] 的范围内。

注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。

示例 1:

输入:s = "3+2*2"
输出:7
示例 2:

输入:s = " 3/2 "
输出:1
示例 3:

输入:s = " 3+5 / 2 "
输出:5

提示:

  • 1 <= s.length <= 3 * 105
  • s 由整数和算符 ('+', '-', '*', '/') 组成,中间由一些空格隔开
  • s 表示一个 有效表达式
  • 表达式中的所有整数都是非负整数,且在范围 [0, 231 - 1] 内
  • 题目数据保证答案是一个 32-bit 整数

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/basic-calculator-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

这道题和224.基本计算器思路一致,利用栈的特点来解决

建立双栈:

  • 使用栈nums:来存放操作数;
  • 使用栈ops:来存放操作符。

与224题不同的是多了几个操作符,且上一题中操作符的优先级一样,这一题有优先级的差别,就利用哈希表来存储优先级,键为操作符,值为优先级,优先级按照数学运算中操作符的优先级来限定。

将字符串s中的所有空格去掉,并转换成字符数组,从前往后进行遍历,根据当前遇到的字符进行分情况讨论:

  • 遇到左括号 (:就将其加入ops中,等待与之匹配的右括号 );
  • 遇到右括号 ):当ops中不为空时,还没遇到与之匹配的左括号时,就将已有的nums和ops进行计算,将结果放入nums中,当遇到与之匹配的左括号时,就将左括号弹出;
  • 遇到数字时:就将当前连续的整数取出,放入nums中;
  • 有新的操作符入栈时,如果ops栈顶操作符优先级 >= 新的操作符的优先级 ,就计算栈内元素,直到操作符为空或者左括号就继续将操作符入栈,后续遍历完s,再进行计算剩下的。

注意点(有一点改变):

1.第一个数可能为负数(-6):这样第一个操作符可能被认为 '减号',计算时没有前面的数与之计算,可以再最开始就加入一个0,变成 0-6这样结果也正好为-6;

2.为了防止括号内出现的首个字符为运算符,当遇到左括号 ( 时,就添加一个0,使之变为 ( 0,其实与224题效果一样,但是我觉得这个更好利于我理解一点。

代码:

  1 class Solution {
2 public int calculate(String s) {
3 Deque<Integer> nums = new ArrayDeque<>();
4 Deque<Character> ops = new ArrayDeque<>();
5 Map<Character, Integer> map = new HashMap<>(){{
6 put('+', 1);
7 put('-', 1);
8 put('*', 2);
9 put('/', 2);
10 put('%', 2);
11 put('^', 3);
12 }};
13 s = s.replaceAll(" ", "");
14 char[] cs = s.toCharArray();
15 int n = cs.length;
16 for(int i = 0; i < n; i++){
17 char c = cs[i];
18 //当前遇到左括号,就加入操作符栈
19 if(c == '('){
20 ops.addLast(c);
21 }else if(c == ')'){
22 //遇到右括号,就计算括号内的数
23 while(!ops.isEmpty()){
24 if(ops.pollLast() != '('){
25 calc(nums, ops);
26 }else{
27 //计算完括号内的数就弹出左括号
28 ops.pollLast();
29 }
30 }
31 }else{
32 if(isNum(c)){
33 int num = 0;
34 int j = i;
35 //取出当前整数
36 while(j < n && isNum(cs[j])){
37 num = num * 10 + (cs[j++] - '0');
38 }
39 nums.addLast(num);
40 i = j -1;
41 }else{
42 //处理遇到左括号时,应该变成(0
43 if(i > 0 && cs[i - 1] == '('){
44 nums.addLast(0);
45 }
46 //如果当前c是操作符就看当前操作符的优先级是否小于等于栈内的优先级
47 //如果是,才计算栈内的
48 while(!ops.isEmpty() && ops.peekLast() != '('){
49 char preop = ops.peekLast();
50 if(map.get(preop) >= map.get(c)){
51 calc(nums, ops);
52 }else{
53 break;
54 }
55 }
56 ops.addLast(c);
57 }
58 }
59 }
60 //遍历完后算剩下的所有
61 while(!ops.isEmpty()){
62 calc(nums, ops);
63 }
64 return nums.peekLast();
65 }
66 //计算方法
67 void calc(Deque<Integer> nums, Deque<Character> ops){
68 //如果操作数为空或者长度小于2
69 if(nums.isEmpty() || nums.size() < 2) return;
70 //如果操作符为空
71 if(ops.isEmpty()) return;
72 int b = nums.pollLast(), a = nums.pollLast();
73 char c = ops.pollLast();
74 int res = 0;
75 switch (c){
76 case '+':
77 res = a + b;
78 break;
79 case '-':
80 res = a - b;
81 break;
82 case '*':
83 res = a * b;
84 break;
85 case '/':
86 res = a / b;
87 break;
88 case '%':
89 res = a % b;
90 break;
91 case '^':
92 res = (int) Math.pow(a, b);
93 break;
94 }
95 nums.addLast(res);
96 }
97 //判断是否为数字
98 boolean isNum(char num){
99 return Character.isDigit(num);
100 }
101 }

 小知识:

1.在数学中优先级:与+、-、*、/相比,幂(^)的优先级最高,最先算。

2.java中运算符的优先级:

力扣227(java)-基本计算器Ⅱ(中等)的更多相关文章

  1. 力扣1689. 十-二进制数的最少数目-C语言实现-中等难度题

    题目 传送门 如果一个十进制数字不含任何前导零,且每一位上的数字不是 0 就是 1 ,那么该数字就是一个 十-二进制数 .例如,101 和 1100 都是 十-二进制数,而 112 和 3001 不是 ...

  2. 力扣1438. 绝对差不超过限制的最长连续子数组-C语言实现-中等难度

    题目 传送门 文本 给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit . 如果不存在满足条 ...

  3. 力扣1052. 爱生气的书店老板-C语言实现-中等难度

    题目 传送门 文本 今天,书店老板有一家店打算试营业 customers.length 分钟.每分钟都有一些顾客(customers[i])会进入书店,所有这些顾客都会在那一分钟结束后离开. 在某些时 ...

  4. 力扣算法经典第一题——两数之和(Java两种方式实现)

    一.题目 难度:简单 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数, 并返回它们的数组下标. 你可以假设每种输入只会对应一 ...

  5. 【力扣leetcode】-787. K站中转内最便宜的航班

    题目描述: 有 n 个城市通过一些航班连接.给你一个数组 flights ,其中 flights[i] = [fromi, toi, pricei] ,表示该航班都从城市 fromi 开始,以价格 p ...

  6. 力扣算法题—069x的平方根

    实现 int sqrt(int x) 函数. 计算并返回 x 的平方根,其中 x 是非负整数. 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去. 示例 1: 输入: 4 输出: 2 示例 ...

  7. JS数据结构第六篇 --- 二叉树力扣练习题

    1.第226题:翻转二叉树 递归+迭代两种实现方式: /** 反转二叉树 * Definition for a binary tree node. * function TreeNode(val) { ...

  8. 力扣(LeetCode)删除排序链表中的重复元素II 个人题解

    给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字. 思路和上一题类似(参考 力扣(LeetCode)删除排序链表中的重复元素 个人题解)) 只不过这里需要用到一个前 ...

  9. C++双指针滑动和利用Vector实现无重复字符的最长子串—力扣算法

    题目: 力扣原题链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/ 给定一个字符串, ...

  10. LeetCode 1244. 力扣排行榜

    地址 https://www.acwing.com/solution/LeetCode/content/5765/ 题目描述新一轮的「力扣杯」编程大赛即将启动,为了动态显示参赛者的得分数据,需要设计一 ...

随机推荐

  1. 【开源库推荐】#1 SpiderMan 可快速查看Android闪退崩溃日志

    原文:https://stars-one.site/2020/12/22/android-log-spiderman 开发Android的时候想必大家都遭受过这种经历: 用户手机上App闪退了,但是我 ...

  2. 记一次maven不下来的经历

    起因:自己手动搭建个项目,参考公司项目使用了很多依赖,但是当自己maven时候发现一个依赖怎么也down不下来,就此展开了一番折腾 这个依赖叫 <dependency> <group ...

  3. 27_H.264解码实战

    目录 使用FFmpeg命令进行H.264解码 使用FFmpeg代码进行H.264解码 1.获取解码器 3.创建解析器上下文 4.创建AVPacket 5.创建AVFrame 6.打开解码器 7.打开文 ...

  4. 浅谈React与SolidJS对于JSX的应用

    React将JSX这一概念深入人心.但,并非只有React利用了JSX,VUE.SolidJS等JS库或者框架都使用了JSX这一概念.网上已经有大量关于JSX的概念与形式的讲述文章,不在本文的讨论范围 ...

  5. 活动报名|3DCAT实时渲染云行业生态合作系列沙龙之“云XR如何赋能虚拟仿真实验教学”线上活动邀您参会

    当前,虚拟现实发展方兴未艾,"XR+教育"融合发展前景广阔. 3DCAT实时渲染云积极联动教育行业渠道商等生态合作伙伴,合力打造"虚拟现实实验室"." ...

  6. 记录--开局一张图,构建神奇的 CSS 效果

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 假设,我们有这样一张 Gif 图: 利用 CSS,我们尝试来搞一些事情. 图片的 Glitch Art 风 在这篇文章中 --CSS 故障 ...

  7. 记录--从原理分析vue开发环境搭建的全部过程

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 平时大家开发vue项目的时候,相信大部分人都是使用 vue-cli脚手架生成的项目架构,然后 npm run install 安装依赖,n ...

  8. 在Centos7上安装Redis6

    一.背景 Redis是一个非常流行的NOSQL数据库,拥有的数据类型非常丰富,此处我们简单记录一下在Centos7上是如何安装Redis6的.Redis的安装是推荐使用源码进行安装的. 二.安装步骤 ...

  9. ARM之AXI总线协议初试

    AXI总线协议的学习 1.AXI总线的初步认识 What is AXI? AXI is part of ARM AMBA, a family of micro controller buses fir ...

  10. debian12 linux 安装xfce4

    1.安装显示服务器 sudo apt install xorg 2.安装xfce sudo apt install xfce4 xfce4-goodies 3.安装显示管理器 sudo apt ins ...