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. 《Python 3网络爬虫开发实战中文》超清PDF+源代码+书籍软件包

    <Python 3网络爬虫开发实战中文>PDF+源代码+书籍软件包 下载: 链接:https://pan.baidu.com/s/18yqCr7i9x_vTazuMPzL23Q 提取码:i ...

  2. CentOS 6.5 下安装及使用中文输入法

    第一次在本机环境下搭载Linux环境,但搭载后发现在CentOS 6.5只能英文输入,于是试着安装并启用中文输入法,经过一翻折腾,实现了在终端和自带火狐浏览器下支持中文输入法. CentOS下安装中文 ...

  3. VMware下的Centos7实践Kvm虚拟化(通俗易懂)

    虽然网上已经有很多关于kvm安装的教程了,但我还是看得头晕,有的教程里安装的包很多,有的很少,也没说明那些安装包的作用是干嘛的,用的命令也不一样,也没解释命令的意思是什么. 我重新写一个教程,尽量通俗 ...

  4. linux修改时间显示格式

    1. 问题描述 Linux下经常使用 "ls - ll"命令查看文件夹或文件创建及权限信息,但是满屏的Mar .May.Jul有点小难受. 2. 解决方案 修改bash_profi ...

  5. 个人永久性免费-Excel催化剂功能第20波-Excel与Sqlserver零门槛交互-数据上传篇

    Excel作为众多数据存储的交换介质,在不同的系统内的数据很少可以很连贯地进行整合分析,一般的业务系统都会提供导出Excel作为标配功能供用户使用系统内生成的数据. 此时最大的问题是,Excel很维去 ...

  6. oracle总结: INTERVAL DAY TO SECOND, 但却获得 NUMBER

    遇到问题: INTERVAL DAY TO SECOND, 但却获得 NUMBER 操作步骤 在查询oracle数据库的时候使用到了系统提供的函数:trunc ( trunc(tb.safedate ...

  7. Android调用系统分享功能总结

    Android分享-调用系统自带的分享功能 实现分享功能的几个办法 1.调用系统的分享功能 2.通过第三方SDK,如ShareSDK,友盟等 3.自行使用各自平台的SDK,比如QQ,微信,微博各自的S ...

  8. baserecyclerviewadapterhelper -- setOnItemChildClickListener出现的问题

    出现问题 使用baserecyclerviewadapterhelper 的时候使用 adapter.setOnItemChildClickListener()方法,点击没有反应. adapter.s ...

  9. hdu6395 Sequence(分段矩阵快速幂)

    Sequence 题目传送门 解题思路 可以比较容易的推出矩阵方程,但是由于p/i向下取整的值在变,所以要根据p/i的变化将矩阵分段快速幂.p/i一共有sqrt(p)种结果,所以最多可以分为sqrt( ...

  10. Python连载24-函数list&read&seek

    一. 函数list (1)定义:用打开的文件作为参数,把文件内的每一行内容作为一个元素 (2)格式:list(文件) (3)例子: with open(r"test01.txt", ...