1 2 3 4 5 6 7 8 9 = 110,在數字間填入加號或者減號(可以不填,但不能填入其它符號)使等式成立。
阿新 • • 發佈:2019-02-10
一共有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
成功: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]; // 交替 } } } }