【问题标题】:Finding all possible combinations of a given array in Java在Java中查找给定数组的所有可能组合
【发布时间】:2015-02-13 06:57:07
【问题描述】:

我正在研究 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]);
            }
        }
    }
}

【问题讨论】:

    标签: java arrays combinations


    【解决方案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
    

    【讨论】:

    • 检查 OP 的答案,你会发现他想要状态 (2, 1, 1)。这是到达(2,1,1) 的一种可能途径:(4,3,2)-&gt;(4,3,1)-&gt;(4,2,1)-&gt;(4,1,1)-&gt;(3,1,1)-&gt;(2,1,1)。停止约束不是any value == 1,而是any value &lt; 1。引用来自 OP:until the value 1 is reached at each index.
    • 谢谢,你是对的,我误解了问题陈述:)
    【解决方案2】:

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

    【讨论】:

    • 不,这是不正确的,OP 要求all possible combinations given an arbitrary starting array, by decrementing the values one at a time,而您的回答基本上只是交换了起始数组中的所有元素。请参考他的答案数组。
    【解决方案3】:
    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;
        }
    }
    

    【讨论】:

    • 然后呢?没有说明?你想告诉我们什么?您需要详细说明为什么您的答案会解决问题。
    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-04
      相关资源
      最近更新 更多