题解 | #24点运算#
24点运算
http://www.nowcoder.com/practice/7e124483271e4c979a82eb2956544f9d
- 实际上是允许有括号的
- 先将输入的字母转换成待处理的数字
- 要通过input得到sum。即:遍历每个input元素(正负不能改变),加减乘除剩下的元素,递归判断能否得到对应的sum加减乘除。注意除的时候,余数必须为0
- 计算完成后,将处理的数字转换成字母,注意开头的+号是不需要的
import java.util.Scanner;
/**
* class com.sloera.nowcoder
* user sloera
* date 2022/2/27
*/
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNextLine()) { // 注意 while 处理多个 case
final String s = in.nextLine();
String result = resolve(s);
System.out.println(result);
}
}
private static String resolve(String s) {
// 3.输入4张牌为字符串形式,以一个空格隔开,首尾无空格;如果输入的4张牌中包含大小王,则输出字符串“ERROR”,表示无法运算;
if (s.contains("joker") || s.contains("JOKER")) {
return "ERROR";
}
final String[] split = s.split("\\s+");
int[] input = new int[split.length];
// 得到输入的数字
// 2.牌面2~10对应的权值为2~10, J、Q、K、A权值分别为为11、12、13、1;
for (int i = 0; i < split.length; i++) {
switch (split[i]) {
case "J": input[i] = 11; break;
case "Q": input[i] = 12; break;
case "K": input[i] = 13; break;
case "A": input[i] = 1; break;
default:
input[i] = Integer.parseInt(split[i]);
}
}
// 计算是否能得到24点
final char[] operators = new char[4];
final int[] number = new int[4];
boolean flag = canculate(operators, number, input, 24);
if (flag) {
final StringBuilder stringBuilder = new StringBuilder();
for (int i = number.length-1; i >= 0; i--) {
if (i != number.length - 1 || operators[i] != '+') {
stringBuilder.append(operators[i]);
}
if (number[i] == 1) {
stringBuilder.append('A');
} else if (number[i] == 11) {
stringBuilder.append('J');
}else if (number[i] == 12) {
stringBuilder.append('Q');
}else if (number[i] == 13) {
stringBuilder.append('K');
} else {
stringBuilder.append(number[i]);
}
}
return stringBuilder.toString();
}
return "NONE";
}
/**
* 是否能由 input 中的数字,计算出sum
*
* @param operators 操作符记录
* @param number 数字计算顺序
* @param input 可选数字
* @param sum 总数
* @return boolean
* @date 2022/2/27
*/
private static boolean canculate(char[] operators, int[] number, int[] input, int sum) {
if (input.length == 1) {
if (input[0] == sum) {
operators[3] = '+';
number[3] = sum;
return true;
}
}
for (int i = 0; i < input.length; i++) {
int[] newInput = getNewInput(input, i);
// ? = sum + input[i]
if (canculate(operators, number, newInput, sum + input[i])) {
// 这里记录的是input[i], ? 已经在递归里面记录了
operators[operators.length - newInput.length - 1] = '-';
// 这里记录的是input[i], ? 已经在递归里面记录了
number[number.length - newInput.length - 1] = input[i];
return true;
}
// ? = sum - input[i]
if (canculate(operators, number, newInput, sum - input[i])) {
// 这里记录的是input[i], ? 已经在递归里面记录了
operators[operators.length - newInput.length - 1] = '+';
// 这里记录的是input[i], ? 已经在递归里面记录了
number[number.length - newInput.length - 1] = input[i];
return true;
}
// ? = sum * input[i]
if (canculate(operators, number, newInput, sum * input[i])) {
// 这里记录的是input[i], ? 已经在递归里面记录了
operators[operators.length - newInput.length - 1] = '/';
// 这里记录的是input[i], ? 已经在递归里面记录了
number[number.length - newInput.length - 1] = input[i];
return true;
}
// ? = sum / input[i]
if (canculate(operators, number, newInput, sum / input[i]) && (sum % input[i] == 0)) {
// 这里记录的是input[i], ? 已经在递归里面记录了
operators[operators.length - newInput.length - 1] = '*';
// 这里记录的是input[i], ? 已经在递归里面记录了
number[number.length - newInput.length - 1] = input[i];
return true;
}
}
return false;
}
/**
* 获取input中,除index索引所在位置的新数组
*
* @param input 原始数组
* @param index 待去除索引
* @return int[]
* @date 2022/2/27
*/
private static int[] getNewInput(int[] input, int index) {
final int[] ints = new int[input.length - 1];
int j = 0;
for (int i = 0; i < input.length; i++) {
if (i != index) {
ints[j++] = input[i];
}
}
return ints;
}
}