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

Finding all possible combinations of a given array in Java

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

我已经开始处理下面的测试用例,但还没有深入。 我需要一些帮助来解决我的问题。

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]);
            }
        }
    }
}

你正在搜索具有 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;
}

这是一个简单的状态搜索问题。您有一个起始状态,您可以根据一些条件扩展它(创建它的 children)。在您的情况下,通过递减其中一个值,但不低于某个下限。

如果您不熟悉 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
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class New{
    public static void main(String[] args) {
        Scanner in=new Scanner(System.in);
        System.out.println("ENTER THE ARRAY SIZE");
        int n=in.nextInt();
        System.out.println("ENTER THE ARRAY VALUES");
        int[] a=new int[n];
        String s="";
        for(int i=0;i<n;i++)
        {
            a[i]=in.nextInt();
            s=s+(char)a[i];
        }
        List<String> hs=mac(s);
        System.out.println("THE COMBINATIONS ARE");
        for(String str:hs)
        {
            char[] ch=str.toCharArray();
            for(int i=0;i<ch.length;i++)
            {
                System.out.print((int)ch[i]);
            }
            System.out.println();
        }

    }
    public static List<String> mac(String s)
    {
        List<String> ss=new ArrayList<String>();
        if(s==null)
        {
            return null;
        }
        else if(s.length()==0)
        {
            ss.add("");
        }
        else
        {
            String str=s.substring(1);
            char c=s.charAt(0);
            List<String> hs=mac(str);
            for(String st:hs)
            {
                for(int i=0;i<=st.length();i++)
                {
                    ss.add(sru(st,c,i));
                }
            }
        }
        return ss;
    }
    public static String sru(String s,char c,int i)
    {
        String start=s.substring(0,i);
        String end=s.substring(i);
        return start+c+end;
    }
}

更简单的方法: 有一个名为 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
}