Problem Statement

Implement a basic calculator to evaluate a simple expression string.

The expression string contains only non-negative integers, +-*/ operators and empty spaces . The integer division should truncate toward zero.

Example 1:

Input: "3+2*2"
Output: 7

Example 2:

Input: " 3/2 "
Output: 1

Example 3:

Input: " 3+5 / 2 "
Output: 5

Note:

  • You may assume that the given expression is always valid.
  • Do not use the eval built-in library function.

Problem link

Video Tutorial

You can find the detailed video tutorial here

Thought Process

This problem is very similar to Basic Calculator. The difference is there is no parenthesis in this one, but there is * and / . We can use similar thought process by having two stacks,  one stack for the operator and the other for the operands. We just need to pay attention the differentiate the operator's priority. For example, when you currently see a "+" or "-"  and previous operator is "*" or "/", you need to pop up the operator stack and calculate. When you currently see a "*" or "/" and previous operator is "+" or "-", you should just keep pushing operator to stack. Else, they are at the same priority, we just do the normal calculation.

A few caveats

  • Notice number overflow. "0- 2147483648". I don't think leetcode has this test case but it is a valid one. We should use Long.
  • Pay attention to the order when popping out operands and calculate, the order matters.
  • The number might not be just single digit, so need to read the char and convert the numbers

Solutions

Standard generic way

Keep two stacks, operator and operands as explained in the above "Thought Process"

 public int calculate(String s) {
if (s == null || s.length() == 0) {
throw new IllegalArgumentException("invalid input");
} int i = 0;
// even though leetcode does not have this use case System.out.println(ins.calculate("0-2147483648")); // -2147483648
// It can still pass with Integer, but use long for overflow case in general
Stack<Long> operands = new Stack<>();
Stack<Character> operators = new Stack<>();
StringBuilder number = new StringBuilder(); // deal with non single digit numbers while (i < s.length()) {
char c = s.charAt(i);
if (c == ' ') {
i++;
continue;
} if (Character.isDigit(c)) {
number.append(c);
} else if (c == '+' || c == '-' || c == '*' || c == '/') {
if (number.length() != 0) {
operands.push(Long.parseLong(number.toString()));
number = new StringBuilder();
}
// Basically based on different priority of operators
if (operators.isEmpty()) {
operators.push(c);
} else if (!operators.isEmpty() && (c == '*' || c == '/') && (operators.peek() == '+' || operators.peek() == '-')) {
// do nothing, keep pushing because */ has higher priority than +-
operators.push(c);
} else if (!operators.isEmpty() && (c == '+' || c == '-') && (operators.peek() == '*' || operators.peek() == '/')) {
// calculate all previous expressions
while (!operators.isEmpty()) {
operands.push(this.calculateValue(operands, operators.pop()));
}
operators.push(c);
} else {
// only calculating one step, for */, and +- case, one step is fine
operands.push(this.calculateValue(operands, operators.pop()));
operators.push(c);
}
}
i++;
} if (number.length() != 0) {
operands.push(Long.parseLong(number.toString()));
}
// for "3+2*2" case that's why we need a while loop
while (!operators.isEmpty()) {
operands.push(this.calculateValue(operands, operators.pop()));
} return (int)operands.pop().longValue(); // Since it is Long, an object can't be cast to primitive, .longValue first then cast
} private long calculateValue(Stack<Long> operands, char op) {
long o2 = operands.pop();
long o1 = operands.pop(); if (op == '+') {
return o1 + o2;
} else if (op == '-') {
return o1 - o2;
} else if (op == '*') {
return o1 * o2;
} else if (op == '/') {
return o1 / o2;
} else {
throw new IllegalArgumentException("invalid op!");
}
}

Time Complexity: O(N), N is the length of the string

Space Complexity: O(N), extra stack is needed

Use one stack with two passes

Another neat and clean way to solve this problem is also similar to the "Use the sign method with one stack" in Basic Calculator. The idea is in the first pass, only calculate "*" and "/" and push the values into the stack, then have a 2nd pass to do the "+" and "-" calculations.

 // Another thought is having 2 pass, first pass */, second pass +-
// "1 + 2 * 3 / 2" = 4, pretty clean
// "1 - 2 * 3 / 2" = -2
public int calculateTwoPass(String s) {
int len;
if (s == null || (len = s.length()) == 0) {
return 0;
}
Stack<Integer> stack = new Stack<Integer>();
int num = 0;
// This is more like the previous sign
char sign = '+';
for (int i = 0; i < len; i++) {
if (Character.isDigit(s.charAt(i))) {
num = num * 10 + s.charAt(i) - '0';
} if ((!Character.isDigit(s.charAt(i)) && ' ' != s.charAt(i)) || i == len - 1) {
if (sign == '-') {
stack.push(-num);
}
if (sign == '+') {
stack.push(num);
}
if (sign == '*') {
stack.push(stack.pop()*num);
}
if (sign == '/') {
stack.push(stack.pop()/num);
}
// reassign the current sign
sign = s.charAt(i);
num = 0;
}
} int re = 0;
for (int i : stack){
re += i;
}
return re;
}

Time Complexity: O(N), N is the length of the string

Space Complexity: O(N), extra stack is needed

References

Leetcode solution 227: Basic Calculator II的更多相关文章

  1. 【LeetCode】227. Basic Calculator II 解题报告(Python)

    [LeetCode]227. Basic Calculator II 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: h ...

  2. 【LeetCode】227. Basic Calculator II

    Basic Calculator II Implement a basic calculator to evaluate a simple expression string. The express ...

  3. leetcode 224. Basic Calculator 、227. Basic Calculator II

    这种题都要设置一个符号位的变量 224. Basic Calculator 设置数值和符号两个变量,遇到左括号将数值和符号加进栈中 class Solution { public: int calcu ...

  4. [LeetCode] 227. Basic Calculator II 基本计算器之二

    Implement a basic calculator to evaluate a simple expression string. The expression string contains ...

  5. [LeetCode] 227. Basic Calculator II 基本计算器 II

    Implement a basic calculator to evaluate a simple expression string. The expression string contains ...

  6. LeetCode#227.Basic Calculator II

    题目 Implement a basic calculator to evaluate a simple expression string. The expression string contai ...

  7. (medium)LeetCode 227.Basic Calculator II

    Implement a basic calculator to evaluate a simple expression string. The expression string contains ...

  8. Java for LeetCode 227 Basic Calculator II

    Implement a basic calculator to evaluate a simple expression string. The expression string contains ...

  9. 224. Basic Calculator + 227. Basic Calculator II

    ▶ 两个四则表达式运算的题目,第 770 题 Basic Calculator IV 带符号计算不会做 Orz,第 772 题 Basic Calculator III 要收费 Orz. ▶ 自己的全 ...

随机推荐

  1. HDU 1584:蜘蛛牌(DFS)

    http://acm.hdu.edu.cn/showproblem.php?pid=1584 题意:要让小的牌放到大的牌上面最少移动的距离. 思路:看成让大的牌放在小的牌上面了...用一个标记数组vi ...

  2. scrapy实战5 POST方法抓取ajax动态页面(以慕课网APP为例子):

    在手机端打开慕课网,fiddler查看如图注意圈起来的位置 经过分析只有画线的page在变化 上代码: items.py import scrapy class ImoocItem(scrapy.It ...

  3. ubuntu18.04上搭建KVM虚拟机环境超完整过程

    看标题这是篇纯运维的文章.在中小型企业中,一般很少配置专业的运维人员,都是由开发人员兼着.同时,对有志于技术管理的开发人员来说,多了解一些运维及整个软件生命周期的知识,是很有帮助的,因为带团队不仅仅是 ...

  4. 探寻 webpack_bundle_analyzer 原理

    webpack_bundle_analyzer 是什么? 这是webpack官方出品的,对项目中模块依赖关系及体积的分析插件,其界面如下: 问题来了,这是如何来进行统计的? 这里提供一个插件的代码,可 ...

  5. Bzoj 3166 [Heoi2013] Alo 题解

    3166: [Heoi2013]Alo Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1118  Solved: 518[Submit][Status ...

  6. 【较复杂bfs】洪水-C++

    描述 魔法森林的地图是R行C列的矩形.能通行的空地表示为'.',C君倾倒洪水的地点标记为'*',无法通行的巨石阵标记为'X',海狸的巢穴标记为'D',而画家和三只小刺猬的初始位置标记为'S'. 每一分 ...

  7. 小白之入口即化——十分钟看懂while循环,字符串格式化,运算符

    while循环 while循环-死循环 while空格+条件+冒号 缩进+循环体 3.打断死循环 break--终止当前循环 while True: print(123) print(234) bre ...

  8. 嵌入式web服务器BOA的移植及应用

    嵌入式web服务器子系统 一.嵌入式web服务器的控制流程 如下图所示,嵌入式web服务器可实现通过网络远程控制嵌入式开发板,便捷实用. 控制流程:浏览器 --->>>嵌入式开发板 ...

  9. .net持续集成sonarqube篇之sonarqube基本操作(一)

    系列目录 Sonarqube Web管理界面虽然设计的简洁大方,也非常直观,但是由于功能繁多,这对快速入手以及快速定位到想要的功能都是一个挑战,在以后的几个小节里我们简要介绍. OwerView(概览 ...

  10. C#编程之JSON序列化与反序列化

    1.在C#管理NuGet程序包中添加Json.NET 2.C#将对象序列化成JSON字符串 模型类1 /// <summary> /// JSON字符串模型.是否出错 /// </s ...