在各个数字之间插入四则运算的运算符组成算式,
然后计算算式的结果(某些数位之间可以没有运算符,但整个表达式中最少要插入 1 个运算符)。
例如:
1234 -> 1+2×3-4 = 3
9876 -> 9×87+6 = 789
假设这里的条件是,组合算式的计算结果为“将原数字各个数位上的数逆序排列得到的数”,
并且算式的运算按照四则运算的顺序进行(先乘除,后加减)。
那么位于 100~999,符合条件的有以下几种情况。
351 -> 3×51 = 153
621 -> 6×21 = 126
886 -> 8×86 = 688
求:位于 1000~9999,满足上述条件的数。
1.罗列出1000~9999之间的每个数字
2.拆分数字,与运算符组合,拼接成表达式
3.计算表达式的值(①中缀表达式=>后缀表达式(逆波兰表示法) ②计算后缀表达式的值)
4.与第一步罗列出的数字的逆序数字进行比较,如果相等,则输出结果
*5.因为4位数拆成多个数相-,/得到的结果都不足4位;相+若要得到4位数(xxx+x=xxxx),则千位和百位必然是9,又因所求结果为逆序后的数字,所以个位和十位也是9,即999+9=1008,并不符合要求,所以有效的运算符只有乘
public static void main(String[] args) {
String[] op = {"+", "-", "*", "/", ""}; // 作为数字之间的分隔符(可根据思路第5步优化为{"*",""})
// 变量n依次表示指定范围内的每个数字
for (int n = 1000; n < 10000; n++) { // 四位数中间有3个位置可以插入运算符或者""(不插入)
String num = "" + n; // 将数字转为字符串形式,以便通过正则表达式拆分
if (num.matches("\\d*0+$")) continue; // 以0结尾的四位数,反转后不足4位数,直接跳过,从而减少循环次数。
Double expected = Double.parseDouble(new StringBuilder(num).reverse().toString()); // 反转后的数字:期望值
// 罗列出3个位置上的运算符(或"")
for (int i = 0; i < op.length; i++) {
for (int j = 0; j < op.length; j++) {
for (int k = 0; k < op.length; k++) {
// 拼接出算数表达式
String exp = num.charAt(0) + op[i] + num.charAt(1) + op[j] + num.charAt(2) + op[k] + num.charAt(3);
Double res = getResult(exp); // 计算表达式的值,自定义的方法getResult(xx)
// 与期望值比较,相同则输出结果
if (Double.compare(expected, res) == 0) { // java.lang.NullPointerException
System.out.println(num + " -> " + res); // 最终结果:5931 -> 1395.0
}
}
}
}
}
}
// 按照四则运算优先级,计算表达式的值,并返回
private static Double getResult(String exp) {
/* 1.中缀表达式 --> 后缀表达式
1) 通过正则表达式切分算数表达式
2) 从左往右遍历中缀表达式的每个元素:数字和运算符
3) 若是数字,直接存入List
4) 若是符号,则①判断优先级②出栈③入栈:
i. 判断当前符号与栈顶符号(最近一次存入的符号)的优先级
ii. 如果该符号是右括号,或者优先级低于栈顶符号,则栈顶元素依次出栈并存入StringBuilder
iii. 然后将当前符号入栈
5) 遍历结束后,出栈所有运算符
*/
Stack nums = new Stack<>(); // 存放数字
Stack op = new Stack<>(); // 存放符号
List list = new LinkedList(); // 保存数字和+-*/符号
// 拆分出数字和操作符
// \d+(\.\d+)? 表示数字部分,小括号里的是小数部分,?表示0~1次
// (?
// 四则运算
private static double calc(double pre, double next, String op) {
switch (op) {
case "+":
return pre + next;
case "-":
return pre - next;
case "*":
return pre * next;
case "/":
return pre / next; // Java中两个double相除,0为除数不会报错
default:
break;
}
throw new IllegalArgumentException("不支持的操作符!");
}
// 计算运算符的优先级。此处指定:数字越大,优先级越高
private static int opPriority(String op) {
if (op == null) return 0;
switch (op) {
case "(":
return 1;
case "+":
case "-":
return 2;
case "*":
case "/":
return 3;
default:
throw new IllegalArgumentException("不支持的操作符!");
}
}
5931
【Java实现四则运算表达式求值(逆波兰法)】https://blog.csdn.net/qq_22795957/article/details/105872740