简体   繁体   English

java中数组的所有可能组合和子集

[英]All possible combinations and subsets of an array in java

Given an array of variable dimensions.... Eg array={1,2,4,5}给定一个可变维度的数组.... 例如 array={1,2,4,5}

I need a way to generale all possible combinations and subset of the array.我需要一种方法来概括所有可能的组合和数组的子集。

Given an array of n elements I need to have all subsets (all subsets of 1 element, all subset of 2 elements, all subset of n elements) an of each subset all possible permutations.给定一个包含 n 个元素的数组,我需要拥有每个子集的所有子集(1 个元素的所有子集、2 个元素的所有子集、n 个元素的所有子集)和所有可能的排列。

For example result should be:例如结果应该是:

{1}
{2}
{4}
{5}
{1,2}
{1,4}
{1,5}
{2,1}
{2,4}
{2,5}
....
....
{1,2,4,5}
{1,2,5,4}
{1,4,2,5}
{1,5,2,4}
{1,5,4,2}
{2,1,4,5}
{2,1,5,4}
....
....
{5,1,4,2}
{5,1,2,4}
{5,2,4,1}
....
....
etc...

ALL combination!全部组合!

Is there a quick way?有快捷的方法吗? I don't have idea....我不知道....

You should apply 2 steps:您应该应用两个步骤:

  1. You need to find all subsets of the given input.您需要找到给定输入的所有子集。 This set of subsets is called the Power Set .这组子集称为幂集
  2. For each element of this power set (that is, for each subset), you need all Permutations .对于此幂集的每个元素(即每个子集),您需要所有Permutations

This implementation uses some utility classes from a combinatorics project.此实现使用了组合学项目中的一些实用程序类。 The output also contains the empty set {} and is not ordered by the size, but this may easily be done as a postprocessing step.输出还包含空集{}并且不按大小排序,但这可以作为后处理步骤轻松完成。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

public class AllCombinations {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1,2,4,5);

        PowerSetIterable<Integer> powerSet = 
            new PowerSetIterable<Integer>(list);
        for (List<Integer> subset : powerSet)
        {
            PermutationIterable<Integer> permutations = 
                new PermutationIterable<Integer>(subset);
            for (List<Integer> permutation : permutations) {
                System.out.println(permutation);
            }
        }

    }
}

//From https://github.com/javagl/Combinatorics
class PowerSetIterable<T> implements Iterable<List<T>> {
    private final List<T> input;
    private final int numElements;
    public PowerSetIterable(List<T> input) {
        this.input = input;
        numElements = 1 << input.size();
    }

    @Override
    public Iterator<List<T>> iterator() {
        return new Iterator<List<T>>() {
            private int current = 0;

            @Override
            public boolean hasNext() {
                return current < numElements;
            }

            @Override
            public List<T> next() {
                if (!hasNext()) {
                    throw new NoSuchElementException("No more elements");
                }
                List<T> element = new ArrayList<T>();
                for (int i = 0; i < input.size(); i++) {
                    long b = 1 << i;
                    if ((current & b) != 0) {
                        element.add(input.get(i));
                    }
                }
                current++;
                return element;
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException(
                        "May not remove elements from a power set");
            }
        };
    }
}
//From https://github.com/javagl/Combinatorics
class PermutationIterable<T> implements Iterable<List<T>> {
    public static int factorial(int n) {
        int f = 1;
        for (int i = 2; i <= n; i++) {
            f = f * i;
        }
        return f;
    }
    private final List<T> input;
    private final int numPermutations;
    public PermutationIterable(List<T> input) {
        this.input = input;
        numPermutations = factorial(input.size());
    }

    @Override
    public Iterator<List<T>> iterator() {
        if (input.size() == 0) {
            return Collections.<List<T>> singletonList(
                    Collections.<T> emptyList()).iterator();
        }
        return new Iterator<List<T>>() {
            private int current = 0;

            @Override
            public boolean hasNext() {
                return current < numPermutations;
            }

            @Override
            public List<T> next() {
                if (!hasNext()) {
                    throw new NoSuchElementException("No more elements");
                }
                // Adapted from http://en.wikipedia.org/wiki/Permutation
                List<T> result = new ArrayList<T>(input);
                int factorial = numPermutations / input.size();
                for (int i = 0; i < result.size() - 1; i++) {
                    int tempIndex = (current / factorial) % (result.size() - i);
                    T temp = result.get(i + tempIndex);
                    for (int j = i + tempIndex; j > i; j--) {
                        result.set(j, result.get(j - 1));
                    }
                    result.set(i, temp);
                    factorial /= (result.size() - (i + 1));
                }
                current++;
                return result;
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException(
                        "May not remove elements from a permutation");
            }
        };
    }
}

First, you need to find all the subsets of the array which are 2^n sets (including the empty set).首先,您需要找到数组的所有子集,它们是 2^n 个集合(包括空集)。 Then once you find the subsets, loop through each of them and compute it permutation using a simple recursion which you can easily find online.然后,一旦找到子集,就遍历它们中的每一个,并使用可以在网上轻松找到的简单递归来计算它的排列。

The easiest way I know is to loop over i from 1 to 2^n - 1 , where n is the size of the array.我知道的最简单的方法是将i1循环到2^n - 1 ,其中 n 是数组的大小。

The 1s in the bit pattern of i tell you which elements to select. i的位模式中的 1 告诉您要选择哪些元素。

eg: With the array [4, 28, 37, 135] on the 10th loop:例如:在第 10 个循环中使用数组[4, 28, 37, 135]

10 == 1010b

1, 0, 1, 0 tells you to select the first and third elements of the array: [4, 37] . 1, 0, 1, 0 告诉您选择数组的第一个和第三个元素: [4, 37]

Now that you have all combinations of elements in the array, you need to get all permutations, which can be done with some simple recursion.现在您拥有数组中元素的所有组合,您需要获取所有排列,这可以通过一些简单的递归来完成。

pseudocode:伪代码:

function getPermutations(arr)
{
    if length of arr == 1 {
        return [arr]
    } else {
        for i = 0 to highest index of arr {
            sub_arr = copy of arr
            remove element i from sub_arr
            perms = getPermutations(sub_arr)

            for each perm in perms {
                insert arr[i] at beginning of perm
            }
            return perms 
        }
    }
}

I'm providing the first solution it came to my mind for finding all subsets given a List (not the permutations, only the subsets).我正在提供我想到的第一个解决方案,用于查找给定列表的所有子集(不是排列,只有子集)。 The method subSets gives all subsets of a specific size, while allSubSets iterates over the sizes.方法subSets给出特定大小的所有子集,而allSubSets迭代这些大小。 Once you have a list of all subsets, you can implement a permutation function that iterates over this list.一旦你有一个所有子集的列表,你就可以实现一个遍历这个列表的置换函数。

public class Subsets<T> {
    public List<List<T>> allSubSets(List<T> list) {
        List<List<T>> out = new ArrayList<List<T>>();
        for(int i=1; i<=list.size(); i++) {
            List<List<T>> outAux = this.subSets(list, i);
            out.addAll(outAux);
        }
        return out;
    }

    private List<List<T>> subSets(List<T> list, int size) {
        List<List<T>> out = new ArrayList<List<T>>();
        for(int i=0; i<list.size()-size+1;i++) {
            List<T> subset = new ArrayList<T>();
            for (int j=i;j<i+size-1;j++) {
                subset.add(list.get(j));
            }
            if (!(size==1 && i>0)) {
                for (int j=i+size-1;j<list.size();j++) {
                    List<T> newsubset = new ArrayList<T>(subset);
                    newsubset.add(list.get(j));
                    out.add(newsubset);
                }
            }
        }
        return out;
    }
}

To use it:要使用它:

Subsets<Integer> aux = new Subsets<Integer>();
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
List<List<Integer>> out = aux.allSubSets(list);
System.out.println(out);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM