1 2 3 4 5 6 7 8 9 = 110,在数字间填入加号或者减号(可以不填,但不能填入其它符号)使等式成立。

时间:2022-11-05 15:07:49
一共有3^8种可能。 答案: 成功:12+34+56+7-8+9 = 110
成功:12+3+45+67-8-9 = 110
成功:12-3+4-5+6+7+89 = 110
成功:1+2+34+5+67-8+9 = 110
成功:1-2+3+45-6+78-9 = 110
成功:123+4-5-6-7-8+9 = 110
成功:123-4+5-6-7+8-9 = 110
成功:123-4-5+6+7-8-9 = 110
成功:123+4+5+67-89 = 110
成功:1+234-56-78+9 = 110


两种方法:


/**
* Copyright (C) 2012 Lear C
*/

/**
* 1 2 3 4 5 6 7 8 9 = 110
* <p/>
* 在数字间填入加号或者减号(可以不填,但不能填入其它符号)使等式成立。 <br/>
* 一种更好的方法是:<br/>
* 每一个空隙之间都有三种可能,"+", "-", "",所以一共有3^8种可能。
*
* @author Lear
*/
public class Tester2 {

private static final char[] NUMBERS = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};
private static final String[] OPERATORS = {"+", "-", ""};
private static final int RESULT = 110; // 计算结果

public static void main(String[] args) {
sortAndCompute(0, "");
}

private static void sortAndCompute(int numIndex, String buffer) {
// 说明到最后一个字符了
if(numIndex == NUMBERS.length - 1) {
buffer += NUMBERS[numIndex];
String formula = buffer.toString();
if(sum(formula) == RESULT) {
System.out.println(formula + " = " + RESULT);
}
return;
}

for(int operIndex = 0; operIndex < OPERATORS.length; ++operIndex) {
buffer += NUMBERS[numIndex];
buffer += OPERATORS[operIndex];
sortAndCompute(numIndex + 1, buffer);
// 消除前面两个已经添加的字符恢复原状,以便下一次循环的叠加
// 但是当中间连接符变为''的时候,则只删除buffer中的前面一个字符
buffer = operIndex != 2 ? buffer.substring(0, buffer.length() - 2)
: buffer.substring(0, buffer.length() - 1);
}
}

private static int sum(String formula) {
if(formula == null || formula.trim().length() == 0)
throw new IllegalArgumentException("formula is invalid!");

Stack<String> numStack = new Stack<String>();
Stack<String> operStack = new Stack<String>();
StringBuffer numBuffer = new StringBuffer();

formula += "#";// 添加一个结束符到公式末尾便于计算
char[] chs = formula.toCharArray();
for(int index = 0; index < formula.length(); ++index) {
if(chs[index] != '+' && chs[index] != '-' && chs[index] != '#') {
numBuffer.append(chs[index]);
} else {
numStack.push(numBuffer.toString());
numBuffer.delete(0, numBuffer.length());

if(operStack.isEmpty()) operStack.push(chs[index] + "");
else {
int numAft = Integer.parseInt(numStack.pop());
int numBef = Integer.parseInt(numStack.pop());
String oper = operStack.pop();
int sum = oper.equals("+") ? numBef + numAft : numBef - numAft;
numStack.push(sum + "");
operStack.push(chs[index] + "");
}
}
}
return Integer.parseInt(numStack.pop());
}
}




package test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* 1 2 3 4 5 6 7 8 9 = 110
* <p/>
* 在数字间填入加号或者减号(可以不填,但不能填入其它符号)使等式成立。
* @author Lear
*
*/
public class Tester {

private static final char[] NUMBERS = {'1', '2', '3', '4', '5', '6', '7', '8', '9'/**/};
private static final int RESULT = 110;// 计算结果

public static void main(String[] args) {
List<List<String>> all = sort(NUMBERS);
testPrint(all);
for(List<String> aRank : all) {
printEstablishEquation(aRank);
}
}

private static void testPrint(List<List<String>> all) {
for(List<String> aRank : all) {
System.out.println(aRank);
}
}

/**
* 按nums的顺序进行排列组合,最后返回一个List数组,它将包含所有的可能的一个由一列数据的List数组。
* <p/>
* 此为一个递归函数,第一个的组合数字后面的字符都将继续调用此函数以计算出List<List<String>>.<br/>
* 缺点:数据量增大时,将导致内存溢出,而且算法的效率低下
*
* @param nums
* @return 格式:[[1,2,3,4..],[12,3,4,..],[12,34,...],....]
*/
private static List<List<String>> sort(char[] nums) {
if(nums.length == 0) return Collections.emptyList();

List<List<String>> all = new ArrayList<List<String>>();
// 字符数组直接加入此List中
List<String> firstRank = new ArrayList<String>();
for(int i = 0; i < nums.length; ++i) {
firstRank.add(nums[i] + "");
}
all.add(firstRank);

// 组合数字的个数,如:1,2,3,4.... ; 12,3,4,5.. ; 123,4,5.. ; 1234.5 ...
for(int combinationNum = 2; combinationNum <= nums.length; ++combinationNum) {
// 此组合的偏移量,如:12,3.... ; 1,23,4....; 1,2,34,...
for(int offset = 0; offset < nums.length - (combinationNum - 1); ++offset) {
List<String> preRank = new ArrayList<String>();
StringBuilder buffer = new StringBuilder();

for(int i = 0; i < offset; ++i) {// 前
preRank.add(nums[i] + "");
}

for(int i = offset; i < offset + combinationNum; ++i) {// 中
buffer.append(nums[i]);
}
preRank.add(buffer.toString());

// 获取后面的字符数组,然后递归组合
char[] suffix = new char[nums.length - (offset + combinationNum)];
for(int i = offset + combinationNum, index = 0; i < nums.length; ++i, ++index) {// 后
suffix[index] = nums[i];
}
// 例如:12组合的后面 [[3,4,5,6,7...],[34,5,6...],[345...]]
List<List<String>> sufArray = sort(suffix);
// 为里面的所有List<String>添加前面的数字组合,
// 例如:添加12到上面的例子中,使之成为[[12,3,4,...],[12,34...]....]
if(sufArray.size() != 0)
for(List<String> sufRank : sufArray) {
// 组合前后的List
List<String> allRank = new ArrayList<String>();
for(int i = 0; i < preRank.size(); ++i) allRank.add(preRank.get(i));
for(int i = 0; i < sufRank.size(); ++i) allRank.add(sufRank.get(i));
// 添加到all中去
all.add(allRank);
}
else
all.add(preRank);// 说明到末尾了
}
}
return all;
}

private static void printEstablishEquation(List<String> ls) {
char[] operators = {'+', '-'};
StringBuilder buff = new StringBuilder();

// 转换为数字
int[] nums = new int[ls.size()];
for(int i = 0; i < ls.size(); ++i) {
nums[i] = Integer.parseInt(ls.get(i));
}
// 对应的操作符是否变化的数组
boolean[] isOperChanges = new boolean[nums.length - 1];
// 计算每一个isOperChange的变化周期
int[] perOperChangeCounts = new int[isOperChanges.length];
for(int index = 0; index < isOperChanges.length; ++index) {
perOperChangeCounts[index] = (int) Math.pow(2, index);
}
// 可能性的计算次数 2^(nums.length - 1)
int computeCount = (int) Math.pow(2, nums.length -1);
for(int i = 1; i <= computeCount; ++i) {
// 迭代计算
int sum = nums[0];
buff.append(nums[0]);
for(int index = 0; index < nums.length - 1; ++index) {
sum = isOperChanges[index] ? sum - nums[index + 1] : sum + nums[index + 1];
buff.append(isOperChanges[index] ? operators[1] : operators[0]);
buff.append(nums[index + 1]);
}
// 打印
if(sum == RESULT)// 输出等式成立的表达式
System.out.println("成功:" + buff.toString() + " = " + sum);
//else
//System.out.println("失败:" + buff.toString() + " = " + sum);
buff.delete(0, buff.length());

// 操作符交替变化数组的迭代计算。
// 第1操作符,每次交替变化;第2操作符,i每 2^2次变化一次;第3操作符,i每2^3次变化一次
for(int index = 0; index < isOperChanges.length; ++index) {
if(i % perOperChangeCounts[index] == 0)
isOperChanges[index] = !isOperChanges[index];// 交替
}
}

}
}