面试题 16.26. 计算器

面试题 16.26. 计算器

题目详情

采用Java实现。

方法一

维护两个栈,其中一个用来存储操作数,另外一个栈用来存储运算符。遍历字符串,如果是数字,那么直接入操作数栈,如果是操作符,就和运算符栈的栈顶元素比较:当运算符的优先级高于运算符栈的栈顶元素——直接入栈;否则取出运算符栈栈顶元素还有操作符栈栈顶两个元素,进行运算,将运算结果再入运算符栈;继续比较直到当前操作符入栈

public class CalculatorByTwoStack {

    private static final char ADD = '+';
    private static final char SUBTRACT = '-';
    private static final char MULTIPLY = '*';
    private static final char DIVIDE = '/';

    private static final char ZERO_CHAR = '0';

    public int calculate(String s) {

        Stack<Integer> operands = new Stack<>();
        Stack<Character> operators = new Stack<>();

        int num = 0;
        for (int i = 0; i < s.length(); i++) {
            char targetChar = s.charAt(i);
            if (isNumber(targetChar)) {
                num = 10 * num + targetChar - ZERO_CHAR;
            }
            if (isOperator(targetChar) || i == s.length() - 1) {
                operands.push(num);
                num = 0;
            }
            if (isOperator(targetChar)) {
                calculateAndSaveOperator(operands, operators, targetChar);
            }
        }

        while (!operators.isEmpty()) {
            doOneOperator(operands, operators);
        }

        return operands.pop();
    }

    private void calculateAndSaveOperator(Stack<Integer> operands, Stack<Character> operators, char c) {
        while (isOperatorPriorityLowerOrEqualThanTop(c, operators)) {
            doOneOperator(operands, operators);
        }
        operators.push(c);
    }

    private void doOneOperator(Stack<Integer> operands, Stack<Character> operators) {
        Integer topOperand = operands.pop();
        Character operator = operators.pop();
        Integer topNextedOperand = operands.pop();

        if (operator == ADD) {
            operands.push(topNextedOperand + topOperand);
        } else if (operator == SUBTRACT) {
            operands.push(topNextedOperand - topOperand);
        } else if (operator == MULTIPLY) {
            operands.push(topNextedOperand * topOperand);
        } else {
            operands.push(topNextedOperand / topOperand);
        }
    }

    private boolean isOperatorPriorityLowerOrEqualThanTop(char c, Stack<Character> operators) {
        if (operators.isEmpty()) {
            return false;
        }
        Character topOperator = operators.peek();
        return !isOperatorPriorityHigherThanTop(c, topOperator);
    }

    private boolean isOperatorPriorityHigherThanTop(char c, Character topOperator) {
        return (topOperator == ADD || topOperator == SUBTRACT) && (c == MULTIPLY || c == DIVIDE);
    }

    private boolean isOperator(char c) {
        return c == ADD || c == SUBTRACT || c == MULTIPLY || c == DIVIDE;
    }

    private boolean isNumber(char c) {
        return c >= '0' && c <= '9';
    }
}

方法二

维护一个栈,栈中的元素累加起来即是运算结果。默认上一个操作符为’+’,遍历字符串,如果是数字,那么暂时保存下来,向后继续遍历如果遇到操作符(或者字符串末尾),判断该数字的上一个操作符,如果为’+’,则直接将当前数字入栈,如果为’-’,则将当前数字取负数入栈,如果为’*’,将栈顶元素与当前数字相乘后入栈,如果为’/’,将栈顶元素与当前数字相除后入栈。最后将栈中元素进行累加即为运算结果

public class CalculatorByOneStack {
    private static final char ADD = '+';
    private static final char SUBTRACT = '-';
    private static final char MULTIPLY = '*';
    private static final char DIVIDE = '/';

    private static final char ZERO_CHAR = '0';

    public int calculate(String s) {
        Stack<Integer> onlyAddedOperands = new Stack<>();

        char operatorBeforeNumber = ADD;
        int number = 0;
        for (int i = 0; i < s.length(); i++) {
            char currentChar = s.charAt(i);
            if (isNumber(currentChar)) {
                number = number * 10 + currentChar - ZERO_CHAR;
            }
            if (shouldDoCalculate(s, i, currentChar)) {
                calculateAndSave(onlyAddedOperands, operatorBeforeNumber, number);

                operatorBeforeNumber = currentChar;
                number = 0;
            }
            // if currentChar = ' ' continue
        }

        return accumulateAllItems(onlyAddedOperands);
    }

    private boolean shouldDoCalculate(String s, int i, char currentChar) {
        return isOperator(currentChar) || i == s.length() - 1;
    }

    private void calculateAndSave(Stack<Integer> onlyAddedOperands, char operatorBeforeNumber, int number) {
        if (operatorBeforeNumber == ADD) {
            onlyAddedOperands.push(number);
        } else if (operatorBeforeNumber == SUBTRACT) {
            onlyAddedOperands.push(-number);
        } else if (operatorBeforeNumber == MULTIPLY) {
            onlyAddedOperands.push(onlyAddedOperands.pop() * number);
        } else {
            onlyAddedOperands.push(onlyAddedOperands.pop() / number);
        }
    }

    private int accumulateAllItems(Stack<Integer> stack) {
        int result = 0;
        while (!stack.isEmpty()) {
            result += stack.pop();
        }
        return result;
    }

    private boolean isOperator(char c) {
        return c == ADD || c == SUBTRACT || c == MULTIPLY || c == DIVIDE;
    }

    private boolean isNumber(char c) {
        return c >= '0' && c <= '9';
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值