在Java中查找给定数组的所有可能组合

时间:2015-02-13 06:57:08

标签: java arrays combinations

我正在研究Java中的一个问题,找到给定任意起始数组的所有可能组合,方法是逐个减少数组中每个项的值,直到每个索引达到值1。 / p>

我已经开始使用下面的测试用例但是还没有达到目标。 我想帮助解决我的问题。

import org.junit.Assert;
import org.junit.Test;

public class ComboTest
{
    @Test
    public void test()
    {
        int[][] answers = {
            {4, 3, 2}, {3, 3, 2}, {2, 3, 2}, {1, 3, 2}, 
            {4, 2, 2}, {3, 2, 2}, {2, 2, 2}, {1, 2, 2}, 
            {4, 1, 2}, {3, 1, 2}, {2, 1, 2}, {1, 1, 2},

            {4, 3, 1}, {3, 3, 1}, {2, 3, 1}, {1, 3, 1}, 
            {4, 2, 1}, {3, 2, 1}, {2, 2, 1}, {1, 2, 1}, 
            {4, 1, 1}, {3, 1, 1}, {2, 1, 1}, {1, 1, 1},
        };


        int[] start = {4, 3, 2};

        int dim = 1;
        for (int i = 0; i < start.length; i++)
        {
            dim *= start[i];
        }

        int[][] combos = new int[dim][start.length];

        for (int i = 0; i < combos[0].length; i++)
        {
            combos[0][i] = start[i];
        }

        for (int i = 1; i < combos.length; i++)
        {
            for (int j = 0; j < combos[i].length; j++)
            {
                int k = combos[i - 1][j] - 1;

                if (k < 1)
                {
                    k = start[j];
                }

                combos[i][j] = k;
            }
        }

        for (int i = 0; i < combos.length; i++)
        {
            for (int j = 0; j < combos[i].length; j++)
            {
                Assert.assertEquals(answers[i][j], combos[i][j]);
            }
        }
    }
}

4 个答案:

答案 0 :(得分:1)

你搜索具有n个元素的数组的所有排列,所以这已经在这里被问到了

Permutation algorithm for array of integers in Java

这不是我的答案,我只是在提及它

static ArrayList<int[]> permutations(int[] a) {
    ArrayList<int[]> ret = new ArrayList<int[]>();
    permutation(a, 0, ret);
    return ret;
}

public static void permutation(int[] arr, int pos, ArrayList<int[]> list){
    if(arr.length - pos == 1)
        list.add(arr.clone());
    else
        for(int i = pos; i < arr.length; i++){
            swap(arr, pos, i);
            permutation(arr, pos+1, list);
            swap(arr, pos, i);
        }
}

public static void swap(int[] arr, int pos1, int pos2){
    int h = arr[pos1];
    arr[pos1] = arr[pos2];
    arr[pos2] = h;
}

答案 1 :(得分:1)

这是一个简单的状态搜索问题。你有一个起始状态,你可以按照一些标准扩展它(创建它的孩子)。在您的情况下,通过递减其中一个值,但不低于某个下限。

如果您不熟悉DFS或BFS,我建议您阅读这些内容。与此同时,这里是代码(可能解决方案不是您期望的格式,但您可以使用它:D):

public class ComboTest {
    public static class Combo {
        private Integer[] values;

        public Combo(Integer[] values) {
            this.values = values;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + Arrays.hashCode(values);
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (!(obj instanceof Combo)) {
                return false;
            }
            Combo other = (Combo) obj;
            if (!Arrays.equals(values, other.values)) {
                return false;
            }
            return true;
        }

        @Override
        public String toString() {
            return Arrays.toString(values);
        }

    }

    public static Set<Combo> combos(Combo start, int lowerBound) {
        Set<Combo> answers = new HashSet<Combo>();

        compute(start, lowerBound, answers);

        return answers;
    }

    private static void compute(Combo start, int lowerBound, Set<Combo> answers) {
        Deque<Combo> dfsStack = new ArrayDeque<Combo>();

        dfsStack.push(start);

        while (!dfsStack.isEmpty()) {
            Combo current = dfsStack.pop();
            answers.add(current);

            for (Combo next : expand(current, lowerBound)) {
                if (!answers.contains(next)) {
                    dfsStack.push(next);
                }
            }
        }
    }

    private static List<Combo> expand(Combo current, int lowerBound) {
        List<Combo> nexts = new ArrayList<Combo>();

        for (int i = 0; i < current.values.length; i++) {
            if (current.values[i] > lowerBound) {
                Integer[] copyCurrent = Arrays.copyOf(current.values, current.values.length);
                copyCurrent[i]--;
                nexts.add(new Combo(copyCurrent));
            }
        }

        return nexts;
    }

    public static void main(String[] args) {
        Combo start = new Combo(new Integer[] { 4, 3, 2 });
        Set<Combo> combos = combos(start, 1);

        for (Combo combo : combos) {
            System.out.println(combo);
        }

        System.out.println(combos.size());
    }

}

输出:

[4, 3, 1]
[2, 1, 1]
[3, 2, 1]
[1, 1, 2]
[2, 2, 2]
[3, 3, 2]
[4, 3, 2]
[4, 2, 1]
[3, 1, 1]
[2, 1, 2]
[3, 2, 2]
[4, 1, 1]
[4, 2, 2]
[3, 1, 2]
[4, 1, 2]
[1, 3, 1]
[1, 2, 1]
[2, 3, 1]
[1, 3, 2]
[1, 1, 1]
[2, 2, 1]
[3, 3, 1]
[1, 2, 2]
[2, 3, 2]
24

答案 2 :(得分:0)

make superbuild

答案 3 :(得分:-1)

更简单的方法: 有一个名为Google Guava的库,可以为你做这件事。 您可以在此处找到它:https://github.com/google/guava

如果此代码适合您,请尝试,但无论如何都是代码。希望它有帮助:) ...

Collection<List<String>> permutations = null;
String[] foo = //your array in here
permutations = Collections2.permutations(Lists.newArrayList(foo));
//use for each loop to read
for (List<String> permutation : permutations) {
                //Output here
}