带表达式输出的24点游戏,如果只是判断能不能组成24点,那么比较简单,输出所有的表达式不能将中间值保存到list中,需要额外的一个变量去保存中间结果,然后依次保存即可
package xwb.demo.leetcode;
/**
* @Author 17912
* @Date 2021-9-6-006 9:53:24
* @Version 1.0
*/
import java.util.ArrayList;
import java.util.Random;
public class Main {
public static void main(String[] args) {
Random rd = new Random();
Thinker ti = new Thinker();
//随机生成10种数据求符合要求的表达式
for (int j = 1; j < 11; j++) {
ArrayList<Integer> card = new ArrayList<Integer>();
System.out.println("第" + j + "组数据为:");
int t;
for (int i = 0; i < 4; i++) {
t = rd.nextInt(13) + 1;
card.add(t);
System.out.print(t + " ");
}
System.out.println();
ti.count(card, card.size() - 1, 24);
System.out.println();
}
}
}
// 输出表达式类
class Expression {
ArrayList<Integer> num = new ArrayList<Integer>();
ArrayList<String> sign = new ArrayList<String>();
// 重载add()方法对集合增加元素
void add(int n) {
num.add(n);
}
void add(String str) {
sign.add(str);
}
// 获取运算符的优先级,“*与/”大于“+与-”
int getPriority(String s) {
if (sign.equals("+"))
return 1;
if (sign.equals("-"))
return 1;
if (sign.equals("*"))
return 2;
if (sign.equals("/"))
return 2;
return -1;
}
String toString(int la) {
if (la == 0) {
return num.get(0) + sign.get(0) + num.get(1);
} else {
String result = this.toString(la - 1);
//若后面的运算符优先于前面的运算符,前面的表达式带上括号
if (getPriority(sign.get(la)) >= getPriority(sign.get(la - 1)))
result = "(" + result + ")";
result += sign.get(la) + num.get(la + 1);
return result;
}
}
@Override
public String toString() {
return toString(2);
}
// 清除集合内的所有内容
void clear() {
num.clear();
sign.clear();
}
}
class Thinker {
Expression exp = new Expression();
boolean count(ArrayList<Integer> array, int index, int target) {
//集合内为两个数时,穷举6种表达式
if (index == 1) {
if (array.get(0) + array.get(1) == target) {
exp.add(array.get(0));
exp.add(array.get(1));
exp.add("+");
return true;
}
if (array.get(0) - array.get(1) == target) {
exp.add(array.get(0));
exp.add(array.get(1));
exp.add("-");
return true;
}
if (array.get(1) - array.get(0) == target) {
exp.add(array.get(1));
exp.add(array.get(0));
exp.add("-");
return true;
}
if (array.get(0) * array.get(1) == target) {
exp.add(array.get(1));
exp.add(array.get(0));
exp.add("*");
return true;
}
if (array.get(0) * target == array.get(1)) {
exp.add(array.get(0));
exp.add(array.get(1));
exp.add("/");
return true;
}
if (array.get(1) * target == array.get(0)) {
exp.add(array.get(1));
exp.add(array.get(0));
exp.add("/");
return true;
}
return false;
} else {
for (int current = 0; current < array.size(); current++) {
ArrayList<Integer> array1 = new ArrayList<Integer>();
//currentNum为集合内当前读取的数字
int currentNum = array.get(current);
for (int i = 0; i < array.size(); i++) {
if (i != current) {
array1.add(array.get(i));
}
}
if (count(array1, index - 1, target - currentNum)) {
exp.add("+");
exp.add(currentNum);
if (index == 3) {
System.out.println(exp.toString());
exp.clear();
}
if (index != 3) {
return true;
}
}
if (count(array1, index - 1, target + currentNum)) {
exp.add("-");
exp.add(currentNum);
if (index == 3) {
System.out.println(exp.toString());
exp.clear();
}
if (index != 3) {
return true;
}
}
if (count(array1, index - 1, target * currentNum)) {
exp.add("/");
exp.add(currentNum);
if (index == 3) {
System.out.println(exp.toString());
exp.clear();
}
if (index != 3) {
return true;
}
}
if (target % currentNum == 0) {
if (count(array1, index - 1, target / currentNum)) {
exp.add("*");
exp.add(currentNum);
if (index == 3) {
System.out.println(exp.toString());
exp.clear();
}
if (index != 3) {
return true;
}
}
}
}
return false;
}
}
}
不需要输出表达式的:采用回溯法,注意 + 和 * 有重复可以剪枝
public boolean judgePoint24(int[] nums) {
// 转成double
List<Double> list = new ArrayList<>();
for (int num : nums) {
list.add((double) num);
}
return solve(list);
}
private boolean solve(List<Double> list) {
if (list.size() == 0) {
return false;
}
if (list.size() == 1) {
return Math.abs(list.get(0) - 24.0) <= 0.01;
}
for (int i = 0; i < list.size(); i++) {
for (int j = 0; j < list.size(); j++) {
if (i == j) {
continue;
}
Double num1 = list.get(i);
Double num2 = list.get(j);
List<Double> nu = new ArrayList<>();
for (int k1 = 0; k1 < list.size(); k1++) {
if (k1 == i || k1 == j) {
continue;
}
nu.add(list.get(k1));
}
for (int k = 0; k < 4; k++) {
if (k < 2 && j < i) {
continue;
}
double total;
// +
if (k == 0) {
total = num1 + num2;
// *
} else if (k == 1) {
total = num1 * num2;
// /
} else if (k == 2) {
// -
total = num1 - num2;
} else {
if (num2 == 0) {
continue;
} else {
total = num1 / num2;
}
}
nu.add(total);
if (solve(nu)) {
return true;
}
nu.remove(nu.size() - 1);
}
}
}
return false;
}