力扣227(java)-基本计算器Ⅱ(中等)
题目:
给你一个字符串表达式 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)-基本计算器Ⅱ(中等)的更多相关文章
- 力扣1689. 十-二进制数的最少数目-C语言实现-中等难度题
题目 传送门 如果一个十进制数字不含任何前导零,且每一位上的数字不是 0 就是 1 ,那么该数字就是一个 十-二进制数 .例如,101 和 1100 都是 十-二进制数,而 112 和 3001 不是 ...
- 力扣1438. 绝对差不超过限制的最长连续子数组-C语言实现-中等难度
题目 传送门 文本 给你一个整数数组 nums ,和一个表示限制的整数 limit,请你返回最长连续子数组的长度,该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit . 如果不存在满足条 ...
- 力扣1052. 爱生气的书店老板-C语言实现-中等难度
题目 传送门 文本 今天,书店老板有一家店打算试营业 customers.length 分钟.每分钟都有一些顾客(customers[i])会进入书店,所有这些顾客都会在那一分钟结束后离开. 在某些时 ...
- 力扣算法经典第一题——两数之和(Java两种方式实现)
一.题目 难度:简单 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数, 并返回它们的数组下标. 你可以假设每种输入只会对应一 ...
- 【力扣leetcode】-787. K站中转内最便宜的航班
题目描述: 有 n 个城市通过一些航班连接.给你一个数组 flights ,其中 flights[i] = [fromi, toi, pricei] ,表示该航班都从城市 fromi 开始,以价格 p ...
- 力扣算法题—069x的平方根
实现 int sqrt(int x) 函数. 计算并返回 x 的平方根,其中 x 是非负整数. 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去. 示例 1: 输入: 4 输出: 2 示例 ...
- JS数据结构第六篇 --- 二叉树力扣练习题
1.第226题:翻转二叉树 递归+迭代两种实现方式: /** 反转二叉树 * Definition for a binary tree node. * function TreeNode(val) { ...
- 力扣(LeetCode)删除排序链表中的重复元素II 个人题解
给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字. 思路和上一题类似(参考 力扣(LeetCode)删除排序链表中的重复元素 个人题解)) 只不过这里需要用到一个前 ...
- C++双指针滑动和利用Vector实现无重复字符的最长子串—力扣算法
题目: 力扣原题链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/ 给定一个字符串, ...
- LeetCode 1244. 力扣排行榜
地址 https://www.acwing.com/solution/LeetCode/content/5765/ 题目描述新一轮的「力扣杯」编程大赛即将启动,为了动态显示参赛者的得分数据,需要设计一 ...
随机推荐
- KTL 最新版
K,K线,Candle蜡烛图. T,技术分析,工具平台 L,公式Language语言使用c++14,Lite小巧简易. 项目仓库:https://github.com/bbqz007/KTL Core ...
- 12_采样格式&音频重采样
采样格式 通过前面学习我们知道FFmpeg和SDL都有自己的采样格式的表达式,那么他们都表示什么意思呢? FFmpeg的采样格式的表达式: enum AVCodecID { ...... AV_COD ...
- 不使用microlib实现STM32串口printf重定向:
不使用microlib实现STM32串口printf重定向: 突然发现有一篇markdown忘记上传了,补一下 注:使用的是CubeMX生成的工程文件 生成后,在usart.c中添加如下代码: //u ...
- Python伪数据生成器Mimesis 使用
一.**Mimesis的介绍** Mimesis是一个用于Python的high-performance伪数据生成器,它用各种语言为各种目的提供数据.这些假数据可以用来填充测试数据库,创建假API端点 ...
- 三维模型3DTile格式轻量化压缩的遇到常见问题与处理方法分析
三维模型3DTile格式轻量化压缩的遇到常见问题与处理方法分析 三维模型的轻量化压缩是一项技术挑战,特别是在处理复杂的3DTile格式时.下面列举了一些处理过程中可能遇到的常见问题以及相应的处理方法: ...
- objective-c之Class底层结构探索
isa 走位图 在讲 OC->Class 底层类结构之前,先看下下面这张图: 通过isa走位图 得出的结论是: 1,类,父类,元类都包含了 isa, superclass 2,对象isa指向类对 ...
- JS服务端技术—Node.js知识点
[版权声明]未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://www.cnblogs.com/cnb-yuchen/p/18031964 出自[进步*于辰的博客] 目录 1.NP ...
- KingbaseES集群运维案例之---主备库failover后auto-recovery机制
KingbaseES集群运维案例之---主备库failover后auto-recovery机制 案例说明: KingbaseES集群,在备库数据库服务down后,可以实现节点数据库服务的自动恢复:在集 ...
- KingbaseES数据库批量加载数据的最佳方法
前言 本文讨论在KingbaseES数据库服务器中批量加载数据的方法,以及空数据库中的初始数据加载和增量数据加载的最佳做法. 批量加载方法 以下数据加载方法按照从最耗时到最不耗时的顺序排列: 1.运行 ...
- FineReport报表绕过预览直接打印
常规情况下,打印报表的一版操作是: 1.点击相关报表查询页面,展示查询结果,即即将打印的页面 2.点击打印按钮,进入浏览器的打印预览界面 3.点击打印 但是某些时候我们可能会希望不需要点开某张报表即可 ...