您的位置:首页 > 其它

一道递归题

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: