一道递归题
2015-05-28 19:58
330 查看
Solution to Problem 5(You're reading svpino.com,
a blog written by Santiago L. Valdarrama about
software engineering.)
Here is the problem again, just in case you didn't read the previous post:Write a program that outputs all possibilities to put
+or
-or
nothing between the numbers 1, 2, ..., 9 (in this order) such that the result is always 100. For example: 1 + 2 + 34 – 5 + 67 – 8 + 9 = 100
编写一个在1,2,…,9(顺序不能变)数字之间插入+或-或什么都不插入,使得计算结果总是100的程序,并输出所有的可能性。例如:1
+ 2 + 34 – 5 + 67 – 8 + 9 = 100
I think it looks harder than it really is. To solve it, I'd try to decompose the problem into smaller problems (you know, the classic Divide and conquer).
So let's start with what we know:
f(1..9) = 100
Here f is the function that returns our final equation. From here we can break this into 3 other pieces:
1 + f(2..9) = 100
1 - f(2..9) = 100
f(12, 3..9) = 100
The first equation uses an addition, the second uses subtraction, and the third equation concatenates the first two numbers. From here, we get the following:
f(2..9) = 100 - 1 = 99
f(-2, 3..9) = 100 - 1 = 99
f(12, 3..9) = 100
(Note how I moved the negative sign into the function on the second equation to keep the result the same.)
From here, we can keep working on each one of the equations above doing the same process:
2 + f(3..9) = 99
2 - f(3..9) = 99
f(23, 4..9) = 99
-2 + f(3..9) = 99
-2 - f(3..9) = 99
f(-23, 4..9) = 99
12 + f(3..9) = 100
12 - f(3..9) = 100
f(123, 4..9) = 100
You'd have to keep doing this until you completely eliminate the function f. From there, each branch where the equality holds represents a solution to the problem, so you can backtrack your steps to stitch the resultant equation together.
The source code
Of course nobody is going to follow the above solution manually, but it shouldn't be too hard to code it:import java.util.ArrayList; public class Main { private static int TARGET_SUM = 100; private static int[] VALUES = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; static ArrayList add(int digit, String sign, ArrayList branches) { for (int i = 0; i < branches.size(); i++) { branches.set(i, digit + sign + branches.get(i)); } return branches; } static ArrayList f(int sum, int number, int index) { int digit = Math.abs(number % 10); if (index >= VALUES.length) { if (sum == number) { ArrayList result = new ArrayList(); result.add(Integer.toString(digit)); return result; } else { return new ArrayList(); } } ArrayList branch1 = f(sum - number, VALUES[index], index + 1); ArrayList branch2 = f(sum - number, -VALUES[index], index + 1); int concatenatedNumber = number >= 0 ? 10 * number + VALUES[index] : 10 * number - VALUES[index]; ArrayList branch3 = f(sum, concatenatedNumber, index + 1); ArrayList results = new ArrayList(); results.addAll(add(digit, "+", branch1)); results.addAll(add(digit, "-", branch2)); results.addAll(add(digit, "", branch3)); return results; } public static void main(String[] args) { for (String string : f(TARGET_SUM, VALUES[0], 1)) { System.out.println(string); } } }
This returns 11 possible solutions:
1 + 2 + 3 - 4 + 5 + 6 + 78 + 9
1 + 2 + 34 - 5 + 67 - 8 + 9
1 + 23 - 4 + 5 + 6 + 78 - 9
1 + 23 - 4 + 56 + 7 + 8 + 9
12 + 3 + 4 + 5 - 6 - 7 + 89
12 + 3 - 4 + 5 + 67 + 8 + 9
12 - 3 - 4 + 5 - 6 + 7 + 89
123 + 4 - 5 + 67 - 89
123 + 45 - 67 + 8 - 9
123 - 4 - 5 - 6 - 7 + 8 - 9
123 - 45 - 67 + 89
相关文章推荐
- 注册界面的设计与实现
- 分类UIView+Extension:frame直接赋值方法
- hdu 2031(进制转换升级版)
- 原型模式
- 题目1521:二叉树的镜像
- 自动化测试入门指南(1)-- 概述
- java ExecutorService.invokeAny()和ExecutorService.invokeAll()的使用剖析
- linux下查看监听端口对应的进程
- 用Xcode6进行ios开发中,修改模拟器键盘显示中文
- Android开发面试经——6.常见面试官提问Android题②(更新中...)
- Android开发面试经——5.常见面试官提问Android题①
- CS小分队第二阶段冲刺站立会议(5月28日)
- 马哥教育第二十三MySQL基础应用入门
- POJ2153-map
- 多线程实现简单的一对一聊天
- javaWeb笔记--虚拟主机以及虚拟目录映射的配置
- 【NFC】 NfcA/NfcB/NfcF/NfcV/IsoDep/Ndef/Mifare/Felica/Pboc/ISOxxxx 都是些什么鸟玩意?
- 关于java、Android中Math的一些用法
- eclipse搜索的正则表达式
- Android开发面试经——2.常见Android基础笔试题