leetcode:224. 基本计算器 I、227. 基本计算器 II

224.标题基本计算器 I在这里插入图片描述

通用解法就不说了,这里介绍下用正则表达式来解这道题,基本思路是先用正则表达式计算出括号中的子表达式,最后计算整个表达式。代码如下:

import java.util.Arrays;
import java.util.regex.*;

class Solution {
	public int calculate(String s) {
		s = s.replace(" ", "");
		return calculateExp(s);
	}

	Pattern splitPattern = Pattern.compile("\\([\\d\\+\\-]+\\)");
	// 计算表达式
	public int calculateExp(String s) {
		if (s.matches("[\\-]?[\\d]+")) {// 判断是否计算结束
			return Integer.parseInt(s);
		}

		StringBuilder sb = new StringBuilder(s);
		Matcher matcher = splitPattern.matcher(s);
		if (matcher.find()) {
			int start = matcher.start();
			int end = matcher.end();
//			System.err.println(start + " " + end);
			int value = calValue(s.substring(start + 1, end - 1));
			String valueStr = value + "";
			if (value < 0 && start > 0) {// 有点烦,计算结果是负数要处理下
				char op = s.charAt(start - 1);
				if (op == '-') {
					valueStr = "+" + (-value);
				}
				start -= 1;
			}
			sb.replace(start, end, valueStr);
		} else {
			sb.replace(0, s.length(), "" + calValue(s));// 无圆括号的表达式
		}
//		System.out.println(sb);
		return calculateExp(sb.toString());
	}

	// 简单加减表达式计算
	Pattern opPattern = Pattern.compile("[\\-\\+]");
	public int calValue(String exp) {
//		System.err.println(exp);
		Matcher matcher = opPattern.matcher(exp);
		String[] nums = opPattern.split(exp);

		if (null == nums || nums.length < 1) {
			return 0;
		}
		int res = Integer.parseInt(nums[0]);

		for (int i = 1; i < nums.length; i++) {
			if (!matcher.find()) {
				return res;
			}

			int index = matcher.start();
			String operator = exp.substring(index, index + 1);
			switch (operator) {
			case "+":
				res += Integer.parseInt(nums[i]);
				break;
			case "-":
				res -= Integer.parseInt(nums[i]);
				break;
			}
		}

//		System.err.println(exp + "==" + res);
		return res;
	}

}

227.基本计算器 II

在这里插入图片描述
使用通用解法,将中缀表达式转为后缀表达式,然后借助操作数栈求值(由于题设中没有圆括号,所以这里并未进行处理,但只需要新增一个方法单独处理圆括号并得到无圆括号的子表达式(注意递归),依旧调用getCalcQueue即可,其余代码无需变动)代码如下:

import java.util.*;

class Solution {
    public int calculate(String s) {
		return calculateExpr(s);
	}

	public int calculateExpr(String expr) {
		Queue<Object> queue = getCalcQueue(expr);
//		System.out.println(queue);
		return calcQueue(queue);
	}

	// 借助栈计算队列的值
	public int calcQueue(Queue<Object> queue) {
		LinkedList<Integer> stack = new LinkedList<Integer>();// 操作数栈
		while (!queue.isEmpty()) {
			Object obj = queue.poll();
			if (obj instanceof Character) {
				int num2 = stack.pollLast();//弹出栈顶元素
				int num1 = stack.pollLast();
				switch ((Character) obj) {
					case '+':
						stack.add(num1 + num2);//注意顺序
						break;
					case '-':
						stack.add(num1 - num2);//注意顺序
						break;
					case '*':
						stack.add(num1 * num2);//注意顺序
						break;
					case '/':
						stack.add(num1 / num2);//注意顺序
						break;
				}
			} else {
				stack.add(Integer.parseInt((String) obj));//数字则直接压入栈
			}
		}
		return stack.pollLast();//栈顶元素就是结果,当前栈也只会有一个元素了
	}

	// 解析中缀表达式转后缀表达式后获得计算队列(不考虑圆括号)
	public Queue<Object> getCalcQueue(String expr) {
		LinkedList<Character> opStack = new LinkedList<Character>();// 操作符栈
		Queue<Object> queue = new LinkedList<Object>();// 计算队列

		String num = "";
		for (int i = 0; i < expr.length(); i++) {
			char ch = expr.charAt(i);
			if (ch == ' ') {
				continue;
			}

			if (Character.isDigit(ch)) {
				num += ch;
			} else {
				if (!"".equals(num)) {// 读取到数字,直接存入queue中
					queue.add(num);
					num = "";
				}

				if (opStack.isEmpty() || (compareOp(opStack.peekLast(), ch) < 0)) {
					// a.当运算符栈为空或者栈顶操作符的优先级小于当前运算符优先级时(如+和-的优先级低于 * 和 /),直接入栈
					opStack.add(ch);
				} else {
					// b.当运算符不为空时且栈顶操作符的优先级大于或等于当前运算符优先级时,循环执行出栈操作并加入queue中,直到遇到优先级小于当前运算符的元素为止。循环执行完后再将当前运算符压栈。
					while (!opStack.isEmpty() && compareOp(opStack.peekLast(), ch) >= 0) {
						queue.add(opStack.pollLast());
					}
					opStack.add(ch);
				}
			}
		}
		queue.add(num);// 处理最后的数字
		// c.表达式的值读取完后,将操作符栈中的所有元素弹出并加入到queue中
		while (!opStack.isEmpty()) {
			queue.add(opStack.pollLast());
		}
		return queue;
	}

	// 比较运算符的优先级,c1>c2返回1,c1=C2返回0,c1<c2返回-1
	public int compareOp(Character c1, Character c2) {
		if (c1.charValue() == '+' || c1.charValue() == '-') {
			if (c2.charValue() == '+' || c2.charValue() == '-') {
				return 0;
			} else {
				return -1;
			}
		} else {
			if (c2.charValue() == '*' || c2.charValue() == '/') {
				return 0;
			} else {
				return 1;
			}
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值