首页 > 编程语言 >力扣227(java)-基本计算器Ⅱ(中等)

力扣227(java)-基本计算器Ⅱ(中等)

时间:2022-09-05 12:03:47浏览次数:68  
标签:java nums res ops 力扣 括号 操作符 227 优先级

题目:

给你一个字符串表达式 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中运算符的优先级:

标签:java,nums,res,ops,力扣,括号,操作符,227,优先级
From: https://www.cnblogs.com/liu-myu/p/16655021.html

相关文章

  • LeetCode 617 在 JavaScript 中合并两个二叉树
    LeetCode617在JavaScript中合并两个二叉树问题陈述给你两棵二叉树根1和根2.想象一下,当您将其中一个覆盖另一个时,两棵树的某些节点重叠,而其他节点则不重叠。您需......
  • Java接口自动化测试框架系列(八)测试结果通知(钉钉通知)
    通过前七步的框架搭建,此时框架已经可以开始进行接口测试了,但是运行的结果需要手动去项目的工作空间去查看,非常不方便。很多公司使用的钉钉来进行日常办公的沟通,我们也可以......
  • import declarations are not supported by current JavaScript version
    Idea的js文件报错:ImportdeclarationsarenotsupportedbycurrentJavaScriptversion报这个错原因是,vue用的es6的语法,解决的话也很简单,只需要把idea的javaScript的版......
  • [javascript] 闭包问题
    闭包1.闭包的前置知识1.函数的执行上下文环境(Executioncontextoffunction)链接2.作用域(scope)在JavaScript中,对象和函数同样也是变量。在JavaScript中,......
  • [javascript]document的open() write() close()用法
    1、document.open()作用:打开一个新文档,即打开一个流,并擦除当前文档的内容。执行完后会打开一个空的html文档语法:document.open(mimetype,replace)参数:mimetype:可选。......
  • Idea 的Test测试报错:java.lang.IllegalStateException: Failed to load ApplicationC
    转载自:https://www.cnblogs.com/zhian/p/12600429.html因为在Test里面使用了注解@Autowired引入来至bean.xml文件的内容,而在Test没有没有办法自动引入,需要在Test类上加......
  • JavaScript日期处理类库-Moment.js
    JavaScript日期处理类库-Moment.js参考链接日期格式化moment().format('MMMMDoYYYY,h:mm:ssa');//九月5日2022,10:00:10上午moment().format('dddd');......
  • Java反射机制
    一、获取字节码c(三种方法).Class.getClass().Class.forName("完整的全路径")二、获取构造方法1.c通过下列方法得到构造方法的对象con(四种方法)getConstruct......
  • java随笔(七)——多线程(比较详细)
    线程线程是进程中单个的顺序控制流,是一条执行路径单线程:一个进程如果只有一条执行路径,则称为单线程程序多线程:一个进程如果有多条执行路径,则称为多线程程序多线程的实......
  • Java运行机制
    Java运行机制高级语言的运行机制我们编程都是用的高级语言(写汇编和机器语言的大牛们除外),计算机不能直接理解高级语言,只能理解和运行机器语言,所以必须要把高级语言翻译......