最近看到一段面试编码视频:字符串计算加减乘除,发现网上很多是【从左到右遍历,两两计算】,没有考虑优先级事项,一直手痒,周末在家倒弄一下。
题目:给一段字符串计算公式,实现加减乘除运算
eg: 输入:“5*45000+246/123”,输出:225002
输入:“1+2-3”,输出:0
输入:“2-10*1/5”,输出:0
前提:只有正整数参与计算,么有括号,且录入公式一定是可以计算的。
原则:在整个遍历字符串过程中 做 存入计算数组toSum 动作,而这个动作 穿插着 计算高优先级(乘除操作)。
1、从左到右遍历整个字符串,将字符串拆分成计算数组expressionAarray; // 主要是将 多位连续数字 存放到一个index位,作为一个参与计算的数值
2、对计算数组expressionAarray,从左到右开始计算乘除操作,存放到toSum数组。一遍结束后,必然只剩下加减;
3、对toSum数组进行计算,返回最终结果。
优势:简单,易理解。复杂度也就是O(n)级别
弊端:
补充:
// 考虑计算优先级,不考虑括号
private static Integer myCalculate(String expressionString) {
if (null == expressionString || expressionString.length() <= 0) return null;
String[] expressionArray = getExpressionArray(expressionString);
if (expressionArray.length == 1) return Integer.valueOf(expressionArray[0]);
String[] toSum = new String[expressionArray.length];
if(expressionString.contains("*") || expressionString.contains("/")) {
toSum[0] = String.valueOf(expressionArray[0]);
int a = 0, b = 0;
int index = 1; // 控制 toSum的下标
for (int i = 1; i < expressionArray.length-1; i++) {
if(expressionArray[i].equals("*")) {
a = Integer.valueOf(expressionArray[i-1]);
b = Integer.valueOf(expressionArray[i+1]);
toSum[index-1] = String.valueOf(a * b);
expressionArray[i+1] = toSum[index-1];
i++;
} else if (expressionArray[i].equals("/")) {
a = Integer.valueOf(expressionArray[i-1]);
b = Integer.valueOf(expressionArray[i+1]);
toSum[index-1] = String.valueOf(a / b);
expressionArray[i+1] = toSum[index-1];
i++;
} else {
toSum[index] = expressionArray[i];
index++;
}
}
// 防止丢:最后的加减丢数字
if (!(expressionArray[expressionArray.length-2].equals("/") || expressionArray[expressionArray.length-2].equals("*"))) {
toSum[toSum.length - 1] = expressionArray[expressionArray.length - 1];
}
} else {
// 么有*/就直接搬迁复制
for (int i = 0; i < expressionArray.length; i++) {
toSum[i] = expressionArray[i];
}
}
String[] toSumShort = Utils.removeNullValues(toSum);
int result = Integer.valueOf(toSumShort[0]); // 第一个位置必然是 数字
for (int i = 1; i < toSumShort.length-1; i+=2) {
if (toSumShort[i].equals("+")) {
result += Integer.valueOf(toSumShort[i+1]);
} else {
result -= Integer.valueOf(toSumShort[i+1]);
}
}
return result; // 返回最终结果
}
辅助方法:
// 字符串转计算数组
private static String[] getExpressionArray(String expression) {
if (null == expression || expression.length() <= 0) return null;
String[] format = new String[expression.length()];
char[] tokenChars = expression.toCharArray();
int index = 0;
for (int i = 0; i < tokenChars.length; i++) {
if (Character.isLetterOrDigit(tokenChars[i]) || tokenChars[i] == '.') {
if (null == format[index]) {
format[index] = String.valueOf(tokenChars[i]);
} else {
format[index] += String.valueOf(tokenChars[i]);
}
} else {
index++; // 与前面的数字分离
format[index] = String.valueOf(tokenChars[i]);
index++; // 与后面的数字分离
}
}
return Utils.removeNullValues(format);
}
// 去除字符串数组里空元素
public static String[] removeNullValues(String[] array) {
List<String> list = new ArrayList<>();
for (String element : array) {
if (element != null) {
list.add(element);
}
}
return list.toArray(new String[0]);
}
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
// 使用第三方正确答案: 有优先级、小括号。补充:【5*45000+123/456】计算有问题
private static Integer func(String expression) {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
try {
Object result = engine.eval(expression);
return Integer.valueOf(result.toString());
} catch (ScriptException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
System.out.println("func(1+2-3) = " + func("1+2-3"));
System.out.println("myCalculate(1+2-3) = " + myCalculate("1+2-3"));
System.out.println("func(1+2*3) = " + func("1+2*3"));
System.out.println("myCalculate(1+2*3) = " + myCalculate("1+2*3"));
System.out.println("func(1*2+3) = " + func("1*2+3"));
System.out.println("myCalculate(1*2+3) = " + myCalculate("1*2+3"));
System.out.println("func(10-10/5+2) = " + func("10-10/5+2"));
System.out.println("myCalculate(10-10/5+2) = " + myCalculate("10-10/5+2"));
System.out.println("func(2-10*1/5) = " + func("2-10*1/5"));
System.out.println("myCalculate(2-10*1/5) = " + myCalculate("2-10*1/5"));
System.out.println("func(2-10/5*5/2) = " + func("2-10/5*5/2"));
System.out.println("myCalculate(2-10/5*5/2) = " + myCalculate("2-10/5*5/2"));
// 多位数计算
System.out.println("func(400/50-20) = " + func("400/50-20"));
System.out.println("myCalculate(400/50-20) = " + myCalculate("400/50-20"));
System.out.println("func(400/50+2*5) = " + func("400/50+2*5"));
System.out.println("myCalculate(400/50+2*5) = " + myCalculate("400/50+2*5"));
System.out.println("func(1000+200-3000) = " + func("1000+200-3000"));
System.out.println("myCalculate(1000+200-3000) = " + myCalculate("1000+200-3000"));
System.out.println("func(10+20*1051) = " + func("10+20*1051"));
System.out.println("myCalculate(10+20*1051) = " + myCalculate("10+20*1051"));
System.out.println("func(5*45000+246/123) = " + func("5*45000+246/123"));
System.out.println("myCalculate(5*45000+246/123) = " + myCalculate("5*45000+246/123"));
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。