LeetCode 224 Basic Calculator (后缀表达式 栈)

129 篇文章 0 订阅
60 篇文章 0 订阅

Implement a basic calculator to evaluate a simple expression string.

The expression string may contain open ( and closing parentheses ), the plus + or minus sign -, non-negative integers and empty spaces .

You may assume that the given expression is always valid.

Some examples:

"1 + 1" = 2
" 2-1 + 2 " = 3
"(1+(4+5+2)-3)+(6+8)" = 23

Note: Do not use the eval built-in library function.

题目链接:https://leetcode.com/problems/basic-calculator/

题目分析:最中规中矩的做法就是,先中缀表达式转后缀表达式,然后根据后缀表达式计算答案,Java跑了100ms,算是很慢了,中缀转后缀的方法是:

1.若为数字直接加到后面

2.若为'(',入符号栈

3.若为运算符,则将优先级大于等于它的运算符先弹出并记录带答案,再将其入栈,本题运算符只有+,-,优先级相同

4.若为')',弹出运算符直到遇到‘(’

因为可能存在不止1位的数字,所以用一个空格来区分,还有就是连字符串的时候StringBuffer要比String快得多

public class Solution {
    
    public void solve(Stack<Integer> stkNum, char op) {
        int a = stkNum.peek();
        stkNum.pop();
        int b = stkNum.peek();
        stkNum.pop();
        if(op == '+') {
            stkNum.push(b + a);
        }
        else if(op == '-') {
            stkNum.push(b - a);
        }
    }
    
    public String infixToSuffix(String s) {
        StringBuffer sb = new StringBuffer("");
        Stack<Character> stkOp = new Stack<>();
        int num, len = s.length();
        for(int i = 0; i < len; i ++) {
            char ch = s.charAt(i);
            if(ch == ' ') {
                continue;
            }
            else if(ch == '(') {
                stkOp.push(ch);
            }
            else if(ch == '+' || ch == '-') {
                while(stkOp.size() > 0 && stkOp.peek() != '(') {
                    sb.append(stkOp.peek());
                    stkOp.pop();
                }
                stkOp.push(ch);
            }
            else if(ch == ')') {
                while(stkOp.peek() != '(') {
                    sb.append(stkOp.peek());
                    stkOp.pop();
                }
                stkOp.pop();
            }
            else {
                num = 0;
                while(i < len && s.charAt(i) >= '0' && s.charAt(i) <= '9') {
                    sb.append(s.charAt(i));
                    i ++;
                }
                sb.append(' ');
                i --;
            }
        }
        return sb.toString();
    }
    
    public int calculate(String s) {
        Stack<Integer> stkNum = new Stack<>();
        String str = infixToSuffix('(' + s + ')');
        int num = 0;
        //System.out.println("str = " + str);
        for(int i = 0; i < str.length(); i ++) {
            if(str.charAt(i) == '+') {
                solve(stkNum, '+');
            }
            else if(str.charAt(i) == '-') {
                solve(stkNum, '-');
            }
            else {
                num = 0;
                while(str.charAt(i) != ' ') {
                    num = num * 10 + str.charAt(i) - '0';
                    i ++;
                }
                stkNum.push(num);
            }
        }
        return stkNum.peek();
    }
}

本题也可以不用栈,直接用递归解决递归的去处理每对括号,参考discuss里大神做法,短小精悍只跑了3ms

public class Solution {
    public static int calculate(String s) {
        if (s.length() == 0) {
            return 0;
        }
        s = "(" + s + ")";
        int[] pos = {0};
        return eval(s, pos);
    }

    private static int eval(String s, int[] pos) {
        int val = 0, i = pos[0], sign = 1, num = 0;
        while(i < s.length()) {
            char c = s.charAt(i);
            switch(c) {
                case '+': val = val + sign * num; num = 0; sign = 1; i++; break;
                case '-': val = val + sign * num; num = 0; sign = -1; i++; break;
                case '(': pos[0] = i + 1; val = val + sign * eval(s, pos); i = pos[0]; break;
                case ')': pos[0] = i + 1; return val + sign * num; 
                case ' ': i++; continue;
                default : num = num * 10 + c - '0'; i++;
            }
        }
        return val;
    }
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值