让我们说我有一排数字" 1 2 3 4" 我需要获得所有可能的值
1+2+3+4
1+2+3-4
1+2-3+4
1+2-3-4
...
-1-2-3-4
尝试写一个递归 但它有点适用于" 1 2"和" 1 2 3"
它应该适用于1 2 3 ... n
checkSum(0, list.size(), list);
private void checkSum(int start, int end, List<Long> list) {
for (int i = start; i < end; i++){
list.set(i, list.get(i) * (-1L));
printLine(list);
checkSum(i+2, end, list);
}
}
private void printLine(List<Long> list) {
for (int i = 0; i < list.size(); i++) {
if (i > 0)
if (list.get(i) > 0L)
System.out.print("+");
System.out.print(String.valueOf(list.get(i)));
}
System.out.println();
}
答案 0 :(得分:2)
我有一种方法可以给你一些非常酷的想法。
我没有使用递归,递归很好,但是当你使用它时你需要小心内存问题。如果你列出一个大的列表,你可能会面临Stack Overflow错误。
好的,我的解决方案利用了二进制系统。
所以,二进制,counting from 0 to 8
0 0 0 0
0 0 0 1
0 0 1 0
0 0 1 1
0 1 0 0
0 1 0 1
0 1 1 0
0 1 1 1
1 0 0 0
你有吗?你可以把那些视为负面信号。您可以应用蒙版来获取值。
你的面具以1开头,然后继续:
0 0 0 1
0 0 1 0
0 1 0 0
1 0 0 0
以这种方式你可以测试这些值。
所以,代码:
public static void listPermutation(List<Long> l) {
for (int i = 0; i <= Math.pow(2,l.size()) - 1; i++) {
List<Long> l2 = new ArrayList<Long>(l);
applyMask(l2, i);
}
}
public static void applyMask(List<Long> l, long counter) {
long mask = 1L;
for (int i = l.size() - 1; counter >= mask; i--) {
if ((mask & counter) > 0) // here testing if the bit is 1 or 0
l.set(i, l.get(i) * -1);
mask <<= 1;
}
printLine(l); // System.out.println(l);
}
实施例,
List<Long> l = new ArrayList<Long>();
l.add(1l);
l.add(2l);
l.add(3l);
l.add(4l);
listPermutation(l);
结果,
1+2+3+4
1+2+3-4
1+2-3+4
1+2-3-4
1-2+3+4
1-2+3-4
1-2-3+4
1-2-3-4
-1+2+3+4
-1+2+3-4
-1+2-3+4
-1+2-3-4
-1-2+3+4
-1-2+3-4
-1-2-3+4
-1-2-3-4
在速度方面,它还不错:
List<Long> l = new ArrayList<Long>();
l.addAll(Arrays.asList(new Long[] { 1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L, 21L, 22L, 23L, 24L }));
long initTime = System.currentTimeMillis();
listPermutation(l);
long finalTime = System.currentTimeMillis();
System.out.println(finalTime - initTime + " ms");
2833 ms
也许(可能)这不是最好的方法,但我相信这会改善你的想法:)
答案 1 :(得分:1)
以下十亿种方式之一...
public class Thingy {
public static void main(String[] args) {
printAll(0, 0, Arrays.asList(1L, 2L, 3L, 4L), "TEST1> ");
printAll(0, 0, Arrays.asList(5L, 6L, 3L, 8L, 9L), "TEST2> ");
}
private static void printAll(int i, long accumulator, List<Long> source, String output) {
if(i >= source.size()) {
System.out.println(output + " = " + accumulator);
} else {
long n = source.get(i);
printAll(i + 1, accumulator + n, source, output + " + " + n);
printAll(i + 1, accumulator - n, source, output + " - " + n);
}
}
}
...输出
TEST1> + 1 + 2 + 3 + 4 = 10
TEST1> + 1 + 2 + 3 - 4 = 2
TEST1> + 1 + 2 - 3 + 4 = 4
TEST1> + 1 + 2 - 3 - 4 = -4
TEST1> + 1 - 2 + 3 + 4 = 6
TEST1> + 1 - 2 + 3 - 4 = -2
TEST1> + 1 - 2 - 3 + 4 = 0
TEST1> + 1 - 2 - 3 - 4 = -8
TEST1> - 1 + 2 + 3 + 4 = 8
TEST1> - 1 + 2 + 3 - 4 = 0
TEST1> - 1 + 2 - 3 + 4 = 2
TEST1> - 1 + 2 - 3 - 4 = -6
TEST1> - 1 - 2 + 3 + 4 = 4
TEST1> - 1 - 2 + 3 - 4 = -4
TEST1> - 1 - 2 - 3 + 4 = -2
TEST1> - 1 - 2 - 3 - 4 = -10
TEST2> + 5 + 6 + 3 + 8 + 9 = 31
TEST2> + 5 + 6 + 3 + 8 - 9 = 13
TEST2> + 5 + 6 + 3 - 8 + 9 = 15
TEST2> + 5 + 6 + 3 - 8 - 9 = -3
TEST2> + 5 + 6 - 3 + 8 + 9 = 25
TEST2> + 5 + 6 - 3 + 8 - 9 = 7
TEST2> + 5 + 6 - 3 - 8 + 9 = 9
TEST2> + 5 + 6 - 3 - 8 - 9 = -9
TEST2> + 5 - 6 + 3 + 8 + 9 = 19
TEST2> + 5 - 6 + 3 + 8 - 9 = 1
TEST2> + 5 - 6 + 3 - 8 + 9 = 3
TEST2> + 5 - 6 + 3 - 8 - 9 = -15
TEST2> + 5 - 6 - 3 + 8 + 9 = 13
TEST2> + 5 - 6 - 3 + 8 - 9 = -5
TEST2> + 5 - 6 - 3 - 8 + 9 = -3
TEST2> + 5 - 6 - 3 - 8 - 9 = -21
TEST2> - 5 + 6 + 3 + 8 + 9 = 21
TEST2> - 5 + 6 + 3 + 8 - 9 = 3
TEST2> - 5 + 6 + 3 - 8 + 9 = 5
TEST2> - 5 + 6 + 3 - 8 - 9 = -13
TEST2> - 5 + 6 - 3 + 8 + 9 = 15
TEST2> - 5 + 6 - 3 + 8 - 9 = -3
TEST2> - 5 + 6 - 3 - 8 + 9 = -1
TEST2> - 5 + 6 - 3 - 8 - 9 = -19
TEST2> - 5 - 6 + 3 + 8 + 9 = 9
TEST2> - 5 - 6 + 3 + 8 - 9 = -9
TEST2> - 5 - 6 + 3 - 8 + 9 = -7
TEST2> - 5 - 6 + 3 - 8 - 9 = -25
TEST2> - 5 - 6 - 3 + 8 + 9 = 3
TEST2> - 5 - 6 - 3 + 8 - 9 = -15
TEST2> - 5 - 6 - 3 - 8 + 9 = -13
TEST2> - 5 - 6 - 3 - 8 - 9 = -31
答案 2 :(得分:0)
为了您的兴趣,使用Java 8流并且没有递归的解决方案:
public class ComboCollector {
private List<String> list = Collections.singletonList("");
private ComboCollector accept(String n) {
list = Stream.concat(
list.stream().map(v -> v + "+" + n), list.stream().map(v -> v + "-" + n))
.collect(Collectors.toList());
return this;
}
private ComboCollector combine(ComboCollector other) {
other.list.stream().forEach(this::accept);
return this;
}
public Stream<String> getResult() {
return list.stream();
}
}
public static void main(String[] args) {
IntStream.range(1, 10).mapToObj(Integer::toString)
.collect(ComboCollector::new, ComboCollector::accept, ComboCollector::combine)
.getResult().forEach(System.out::println);
}
我不一定推荐这种方法,只是想展示一种与传统递归不同的机制。