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. 前端笔记之React(四)生命周期&Virtual DOM和Diff算法&日历组件开发

    一.React生命周期 一个组件从出生到消亡,在各个阶段React提供给我们调用的接口,就是生命周期. 生命周期这个东西,必须有项目,才知道他们干嘛的. 1.1 Mouting阶段[装载过程] 这个阶 ...

  2. redis RDB 和AOF

    参考文献 Redis源码学习-AOF数据持久化原理分析(0) Redis源码学习-AOF数据持久化原理分析(1) Redis · 特性分析 · AOF Rewrite 分析 深入剖析 redis AO ...

  3. navicat中查重并删除

    # 查询所有重复的数据 SELECT * FROM hao123 WHERE ir_url IN (SELECT ir_url FROM `hao123` GROUP BY ir_url having ...

  4. 环形缓存RingBuf的几种实现方式(数组,链表),及Disruptor的分析

    先贴个头文件的设计: 首先缓冲区中没有任何数据时,nIdWrite.nIdRead读写下标都为0. 为了判断缓冲区中是否还有数据可读或者可写,我判断的依据是:1)当nIdWrite 等于 nIdRea ...

  5. Django前端HTML通过JS实现表格可编辑,动态添加行,回车完成新建文件夹

    功能描述: 点击“新建文件夹”按钮,在table的末尾增加一行:单击页面的新增行,使单元格td变成可编辑状态:输入内容后,当单元格失去焦点时,保存输入的内容:回车后通过AJAX提交后台完成新建文件夹. ...

  6. Nginx Location匹配顺序

    理论部分 文字释义匹配规则如下: 略述: 1.nginx服务器首先在server块的多个location块中搜索是否有标准的uri和请求字符串匹配.如果有多个标准uri可以匹配,就匹配其中匹配度最高的 ...

  7. 学习4:内容# 1.列表 # 2.元祖 # 3.range

    1.列表 列表 -- list -- 容器 有序,可变,支持索引 列表: 存储数据,支持的数据类型很多 字符串,数字,布尔值,列表,集合,元祖,字典, 定义一个列表 lst = ["dsb& ...

  8. 星际旅行(欧拉路,欧拉回路)(20190718 NOIP模拟测试5)

    瞎搞了一个ans+=du*(du-1)/2 wa20分,好桑心(话外音:居然还有二十分,出题人太周到了) 还是判欧拉路 题解没太仔细想,感觉还是kx的思路明白 具体就是:因为每条边要走两遍,可以把一条 ...

  9. [原创]MySQL数据库查询和LVM备份还原学习笔记记录

    一.查询语句类型: 1)简单查询 2)多表查询 3)子查询 4)联合查询 1)简单查询: SELECT * FROM tb_name; SELECT field1,field2 FROM tb_nam ...

  10. 获取文件版本(IE)

    GetFileInfoCUIAction::GetFileVersion2GetSystemDirectory     WCHAR szConfigFile[MAX_PATH + 1];    ::G ...