【问题标题】:All possible combinations and subsets of an array in javajava中数组的所有可能组合和子集
【发布时间】:2014-08-08 13:42:48
【问题描述】:

给定一个可变维度的数组...... 例如。数组={1,2,4,5}

我需要一种方法来概括所有可能的组合和数组的子集。

给定一个包含 n 个元素的数组,我需要拥有所有子集(1 个元素的所有子集、2 个元素的所有子集、n 个元素的所有子集)每个子集的所有可能排列。

例如结果应该是:

{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...

所有组合!

有没有快速的方法? 我不知道....

【问题讨论】:

  • 你尝试过什么,你做了什么?或者,如果您还没有编写任何代码,请尝试写下说明:例如,排列和子集是什么意思?
  • 我没有任何代码...因为我真的很困惑。 Thusitha 的例子产生了所有的排列。我需要所有的组合。这意味着:给定一个数组,我需要拥有所有子集(1 个元素的所有子集、2 个元素的所有子集、n 个元素的所有子集)每个子集的所有可能排列。
  • @assylias 就是这样,结合查找每个集合的排列。

标签: java arrays combinations permutation


【解决方案1】:

您应该应用 2 个步骤:

  1. 您需要找到给定输入的所有子集。这组子集称为Power Set
  2. 对于此幂集的每个元素(即,对于每个子集),您需要所有 Permutations

此实现使用来自combinatorics 项目的一些实用程序类。输出还包含空集 {} 并且不按大小排序,但这可以作为后处理步骤轻松完成。

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

【讨论】:

    【解决方案2】:

    首先,您需要找到数组的所有子集,它们是 2^n 个集合(包括空集)。然后,一旦你找到了子集,遍历它们中的每一个,并使用一个简单的递归计算它的排列,你可以很容易地在网上找到它。

    【讨论】:

      【解决方案3】:

      我知道的最简单的方法是将i1 循环到2^n - 1,其中n 是数组的大小。

      i 位模式中的 1 告诉您选择哪些元素。

      例如:数组[4, 28, 37, 135] 在第 10 个循环中:

      10 == 1010b
      

      1, 0, 1, 0 告诉您选择数组的第一个和第三个元素:[4, 37]

      现在您已经拥有数组中元素的所有组合,您需要获取所有排列,这可以通过一些简单的递归来完成。

      伪代码:

      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 
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        我正在提供我想到的第一个解决方案,用于查找给定列表的所有子集(不是排列,只有子集)。 subSets 方法提供特定大小的所有子集,而 allSubSets 迭代大小。一旦你有了一个所有子集的列表,你就可以实现一个遍历这个列表的置换函数。

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

        使用它:

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

        【讨论】:

          猜你喜欢
          • 2011-08-10
          • 1970-01-01
          • 2014-08-01
          • 2012-03-27
          • 2017-08-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多