【问题标题】:find all combinations of given numbers in a given array size查找给定数组大小中给定数字的所有组合
【发布时间】:2016-05-25 12:30:35
【问题描述】:

我需要从大小 n 中找到由 numbers 数组中的数字组成的所有组合。我尝试使用我在下面编写的函数来执行此操作,但这样做需要大量时间和内存。

有没有更高效的方法?

void createCombinationArray(ArrayList<Integer> numbers, int n, ArrayList<Integer> start) {
    if (start.size() >= n) {
        monthsComb.add(new ArrayList<>(start));
    } else {
        for (Integer x : numbers) {
            start.add(x);
            createCombinationArray(numbers, n, start);
            start.remove(start.lastIndexOf(x));
        }
    }
}

【问题讨论】:

  • numbers 中有k 元素时,您将获得k^n 组合。即使对于相对较小的数字,这也是很多。因此,如果它需要很长时间并且占用大量内存,请不要感到惊讶

标签: java arrays combinations


【解决方案1】:

一种更有效的方法(时间和内存)是将结果存储为int[][] 而不是Collection&lt;List&lt;Integer&gt;&gt;(我假设它是monthsComb 字段的类型)。您可以这样做,因为您知道如果您有 k 个数字,结果将是 Binomial(n, k) n 个数字的组合。

另一种方法(如@Phia-CM 建议的那样)是实现算法的非递归版本。

我知道它们都不容易实现,但这是提高效率的方式。

【讨论】:

    【解决方案2】:

    问问自己是否真的需要提前生成所有这些列表。也许按需生成它们是可以接受的。

    请记住,这些列表中的每一个都可以由具有numbers.length 位、n 或更多位的数字表示。您可以使用这种数据结构来引用它外部的列表。

    用这种行为编写一个 List 实现会非常简单。

    import java.util.BitSet;
    import java.util.List;
    
    public class SelectiveList<T> implements List<T> {
        private final BitSet bitSet;
        private final List<T> list;
    
        public SelectiveList(BitSet bitSet, List<T> list) {
            this.bitSet = bitSet;
            this.list = list;
        }
    
        @Override
        public T get(int index) {
            return list.get(nthOnBit(index));
        }
    
        private int nthOnBit(int n) {
            int onBits = 0;
            int i;
            for (i = bitSet.nextSetBit(0); i >= 0 && onBits < n; i = bitSet.nextSetBit(i + 1)) {
                onBits++;
            }
            if (onBits < n) {
                throw new IllegalArgumentException();
            }
    
            return i;
        }
    
        // etc.
    }
    

    【讨论】:

      【解决方案3】:

      你可以试试这个:

      package combination;
      
      import java.math.BigInteger;
      import java.util.ArrayList;
      import java.util.Arrays;
      import java.util.Iterator;
      import java.util.List;
      
      public class Combination implements Iterator<List<Integer>> {
      
          public Combination(final List<Integer> numbers, final int n) {
              this.numbers = numbers;
              this.n = n;
              this.current = BigInteger.valueOf(0);
              this.radix = BigInteger.valueOf(numbers.size());
              this.size = this.radix.pow(n);
          }
      
          @Override
          public final boolean hasNext() {
              return this.current.compareTo(size) < 0;
          }
      
          @Override
          public final List<Integer> next() {
              List<Integer> result = new ArrayList(this.n);
              BigInteger value = this.current;
              for(int i=0; i<n; i++) {
                  result.add(i, this.numbers.get(
                          value.mod(this.radix).intValueExact()));
                  value = value.divide(this.radix);
              }
              this.current = this.current.add(BigInteger.valueOf(1));
              return result;
          }
      
          private final List<Integer> numbers;
          private final int n;
          private BigInteger current; 
          private final BigInteger size;
          private final BigInteger radix;
      
          public static void main(String[] args) {
              Combination cb = new Combination(Arrays.asList(0, 2, 4, 6), 3);
              while (cb.hasNext()) {
                  System.out.println(cb.next());
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-19
        • 1970-01-01
        • 2021-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多