从较大的数字列表中选择一定数量的不同数字

时间:2013-09-03 09:08:27

标签: java algorithm

这个问题难以用一句话来解释,我似乎也找不到一个好的,简单的方法来做到这一点。我在问:如果我有一个数字列表(数组)(也可能是字符串),让我们说数字最多为7,我想选择5个数字,都是不同的,我怎么能找到所有数字可能的五个数字的不同组合,并将它们保存在一个数组中。

e.g。我有一个7个数字的列表。我只能使用5个不同的数字。我的组合将是:

1. 1 2 3 4 5
2. 1 2 3 4 6
3. 1 2 3 4 7
4. 1 2 3 5 6
5. 1 2 3 5 7

如何编写一个java程序,它将在数组中提供所有这些组合。也将不胜感激。

2 个答案:

答案 0 :(得分:0)

我不打算为您提供完整的解决方案,因为除了针对初始解决方案的一些建议(不一定是最佳解决方案)之外,这对任何人都没有帮助。

到目前为止,最简单的方法是创建任何长度的所有组合并消除所有不长度为5的组合。您可以通过遍历每个输入数量并确定您是否愿意来完成此操作包括它并跟踪你拥有的数字;如果组合最后没有5个数字,则拒绝该组合。

这种天真的方法是嵌套for循环

for(int i=0;i<2;i++){
    //either include the first or not depending on if i is 0 or 1
    for(int j=0;j<2;j++){
          //either include the first or not depending on if i is 0 or 1
          for(........
             ..........
                 built the combination and if its length 5 add it to a collection
          } 
    } 
} 

这当然是硬编码原始输入大小的大小;这可以避免使用递归函数,该函数将正在构建的combinationObject作为参数,inputNumbers和当前递归深度(因此它知道要决定哪个输入数字。它会返回一些集合(例如hashset或arraylist),它将是递归方面“在下面”生成的所有集合的总和(在每个级别,函数将自己调用两次;一次用于include,一次用于不包括。< / p>

这个递归函数看起来像

public Collection<CombinationObject> addDigit(CombinationObject combinationSoFar, InputObject numbersToChooseFrom, int depth){
      if (depth==numbersToChooseFrom.size()){
           Collection<CombinationObject> collection=new HashSet<CombinationObject>();
           collection.add(combinationSoFar.add(numbersToChooseFrom.get(depth); //add a digit
           collection.add(combinationSoFar); //don't add a digit

           return collection;
      }else{
           Collection<CombinationObject> collection=new HashSet<CombinationObject>();
           collection.addAll(addDigit(combinationSoFar.add(InputObject.getDigit(depth), InputObject numbersToChooseFrom,depth+1);
           collection.addAll(addDigit(combinationSoFar, InputObject numbersToChooseFrom,depth+1);
           return collection;
      }
}

的Nb。 combinationSoFar应该是不可变的,而.add方法应该返回一个新对象

这在效率方面可能不是一个理想的解决方案,但希望能帮助你开始

答案 1 :(得分:0)

你可以使用递归(不是我经常说的)来做到这一点

public static <T> void combinations(List<T> values, int maxCount, CombinationListener<T> listener) {
    List<T> comb = (List<T>) Arrays.asList(new Object[maxCount]);
    boolean[] used = new boolean[values.size()];
    combinations0(values, used, comb, 0, maxCount, listener);

}

static <T> void combinations0(List<T> values, boolean[] used, List<T> comb, int idx, int maxCount, CombinationListener<T> listener) {
    if (idx == maxCount) {
        listener.onComlination(comb);
        return;
    }
    for (int i = 0; i < values.size(); i++) {
        if (used[i]) continue;

        used[i] = true;
        comb.set(idx, values.get(i));
        combinations0(values, used, comb, idx + 1, maxCount, listener);
        used[i] = false;
    }
}

public static void main(String[] args) {
    combinations(Arrays.asList(1, 2, 3, 4, 5, 6, 7), 5, new CombinationListener<Integer>() {
        @Override
        public void onComlination(List<Integer> list) {
            System.out.println(list);
        }
    });
}

interface CombinationListener<T> {
    void onComlination(List<T> list);
}

打印

[1, 2, 3, 4, 5]
[1, 2, 3, 4, 6]
[1, 2, 3, 4, 7]
[1, 2, 3, 5, 4]
[1, 2, 3, 5, 6]
[1, 2, 3, 5, 7]
[1, 2, 3, 6, 4]
[1, 2, 3, 6, 5]
[1, 2, 3, 6, 7]
... many deleted ...
[7, 6, 5, 2, 4]
[7, 6, 5, 3, 1]
[7, 6, 5, 3, 2]
[7, 6, 5, 3, 4]
[7, 6, 5, 4, 1]
[7, 6, 5, 4, 2]
[7, 6, 5, 4, 3]