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. 5分钟快速部署ownCloud私有云盘存储系统

    ownCloud 是一个开源免费专业的私有云存储项目,它能帮你快速在个人电脑或服务器上架设一套专属的私有云文件同步网盘,可以像 Dropbox 那样实现文件跨平台同步.共享.版本控制.团队协作等等.o ...

  2. centos下安装色彩scrapy

    一.安装Python2.7.6 更新CentOS lib库文件 yum -y update 安装开发工具包 yum groupinstall -y development 安装扩展包 yum inst ...

  3. Java 源码学习系列(三)——Integer

    Integer 类在对象中包装了一个基本类型 int 的值.Integer 类型的对象包含一个 int 类型的字段. 此外,该类提供了多个方法,能在 int 类型和 String 类型之间互相转换,还 ...

  4. WinForm控件之【ListView】

    基本介绍 项列表控件,拥有五种不同视图的样式供展示项集合. 常设置属性 Columns:‘详细信息’视图中用来显示的列: Groups:ListView列表中的组,将列表各项分组区域展示: Horiz ...

  5. mvc区分页面内请求判断是否是Html.action或Html.RenderAction请求

    ControllerContext.IsChildAction 来判断,如果用Html.Action或Html.RenderAction方法,这个属性返回true,否则返回false

  6. 掌握简单的Makefile文件编程

    Makefile描述整个程序的编译.链接规则 其中还包括了工程中用到的那些源文件及需要产生的目标文件 1)Makefile编程规则 目标(唯一):依赖(可多个) 命令... 伪目标 .PHONY:cl ...

  7. .net持续集成cake篇之使用vs或者vscode来辅助开发cake脚本

    使用Visual Studio来开发工具 前面我们都是通过手写或者复制的方法来编写Cake文件,Cake使用的是C#语言,如果仅使用简单的文本编辑器来编写显然效率是非常低下的,本节我们讲解如何使用ca ...

  8. Hive之函数与自定义函数

    系统自带的函数 1)查看系统自带的函数 hive> show functions; 2)显示自带的函数的用法 hive> desc function upper; 3)详细显示自带的函数的 ...

  9. Oracle RAC运维所遇问题记录一

    Oracle11gR2,版本11.2.0.4集群测试环境运行正常 主机名:rac1,rac2 hosts文件: # Public172.17.188.12 rac1172.17.188.13 rac2 ...

  10. Visual Studio 2015 WinForm应用程序打包教程

    最近开发了一个小软件.由于需要打包.网上找了一些资料.然后整合了起来.希望对大家有所帮助.不全面请见谅. 本人开发工具用的是Visual Studio 2015  打包控件 InstallShield ...