java获取所有可能的变体(正面和负面)

时间:2015-10-15 13:09:07

标签: java recursion

让我们说我有一排数字" 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();
}

3 个答案:

答案 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);
}

我不一定推荐这种方法,只是想展示一种与传统递归不同的机制。