繁体   English   中英

番石榴收藏:限制排列大小

[英]Guava Collections : limit permutation size

使用guava 12 Collections2.permutations() ,我想知道是否可以限制排列的大小?

更准确地说,我想在n个元素的列表中获得k个大小的排列列表,而不是获得所有n个大小的排列的列表。

目前,如果我传递4个水果的列表,那么permutations()将返回24个4大小排列的列表,尽管我只对检索4个唯一大小3个排列感兴趣。

说我有4个水果的清单:

["Banana", "Apple", "Orange", "Peach"]

如果我只对3号排列感兴趣,我希望返回以下内容:

["Banana", "Apple", "Orange"]
["Banana", "Apple", "Peach"]
["Banana", "Orange", "Peach"]
["Apple", "Orange", "Peach"]

任何人都可以提供解决方案的任何提示吗? 谢谢 !

此代码计算出变体,然后在每个唯一的3组上运行排列。

即对于“A”,“B”,“C”,“D”,可能性为[[A,B,C],[A,B,D],[A,C,D],[B,C, d]。 然后我们计算每个三人组(或n-some)的排列,并将可能性附加到列表中。

PermutationsOfN.processSubsets(List set,int k)返回:[[A,B,C],[A,B,D],[A,C,D],[B,C,D]]

更进一步PermutationsOfN.permutations(List list,int size)返回:
[[A,B,C],[A,C,B],[C,A,B],[C,B,A],[B,C,A],[B,A,C],[ A,B,D],[A,D,B],[D,A,B],[D,B,A],[B,D,A],[B,A,D],[A, C,D],[A,D,C],[D,A,C],[D,C,A],[C,D,A],[C,A,D],[B,C, D],[B,D,C],[D,B,C],[D,C,B],[C,D,B],[C,B,D]]

import java.util.Collection;
import java.util.List;

import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;

public class PermutationsOfN<T> {
  public static void main( String[] args ) {
    List<String> f = Lists.newArrayList( "A", "B", "C", "D" );
    PermutationsOfN<String> g = new PermutationsOfN<String>();
    System.out.println( String.format( "n=1 subsets %s", g.processSubsets( f, 1 ) ) );
    System.out.println( String.format( "n=1 permutations %s", g.permutations( f, 1 ) ) );
    System.out.println( String.format( "n=2 subsets %s", g.processSubsets( f, 2 ) ) );
    System.out.println( String.format( "n=2 permutations %s", g.permutations( f, 2 ) ) );
    System.out.println( String.format( "n=3 subsets %s", g.processSubsets( f, 3 ) ) );
    System.out.println( String.format( "n=3 permutations %s", g.permutations( f, 3 ) ) );
    System.out.println( String.format( "n=4 subsets %s", g.processSubsets( f, 4 ) ) );
    System.out.println( String.format( "n=4 permutations %s", g.permutations( f, 4 ) ) );
    System.out.println( String.format( "n=5 subsets %s", g.processSubsets( f, 5 ) ) );
    System.out.println( String.format( "n=5 permutations %s", g.permutations( f, 5 ) ) );
  }

  public List<List<T>> processSubsets( List<T> set, int k ) {
    if ( k > set.size() ) {
      k = set.size();
    }
    List<List<T>> result = Lists.newArrayList();
    List<T> subset = Lists.newArrayListWithCapacity( k );
    for ( int i = 0; i < k; i++ ) {
      subset.add( null );
    }
    return processLargerSubsets( result, set, subset, 0, 0 );
  }

  private List<List<T>> processLargerSubsets( List<List<T>> result, List<T> set, List<T> subset, int subsetSize, int nextIndex ) {
    if ( subsetSize == subset.size() ) {
      result.add( ImmutableList.copyOf( subset ) );
    } else {
      for ( int j = nextIndex; j < set.size(); j++ ) {
        subset.set( subsetSize, set.get( j ) );
        processLargerSubsets( result, set, subset, subsetSize + 1, j + 1 );
      }
    }
    return result;
  }

  public Collection<List<T>> permutations( List<T> list, int size ) {
    Collection<List<T>> all = Lists.newArrayList();
    if ( list.size() < size ) {
      size = list.size();
    }
    if ( list.size() == size ) {
      all.addAll( Collections2.permutations( list ) );
    } else {
      for ( List<T> p : processSubsets( list, size ) ) {
        all.addAll( Collections2.permutations( p ) );
      }
    }
    return all;
  }
}

特别提到了meriton,他的答案在这里帮助我解决了问题。

虽然您可以提交功能请求 ,但没有内置的Guava功能可以执行此操作。

如果我正在编写一个实现,我认为最简单的方法是迭代组合(使用Gosper的hack ),然后使用Collections2.permutations进行迭代。

或者,基于此Python代码 ,看起来对常规置换生成算法的一些小修改就足够了。

直接回答你的问题是:

public static <X> List<List<X>> test(List<X> input, final int n, final int m) {
    int x = 0;

    List<List<X>> newPerm = Lists.newArrayList();
    Collection<List<X>> perm = Collections2.permutations(input);
    for (Iterator<List<X>> it = perm.iterator(); it.hasNext(); x++) {
        if (x >= n) {
            break;
        }

        List<X> list = it.next();
        newPerm.add(Lists.partition(list, m).get(0));
    }

    return newPerm;
}

接着:

    List<String> list = Lists.newArrayList("Banana", "Apple", "Orange", "Peach");
    List<List<String>> answer = test(list, 4, 3);
    for (List<String> list1 : answer) {
        System.out.println(list1);
    }

但它只需要第一个,而不是一个特别定义的集合,你可能会更好地遵循路易斯的建议

暂无
暂无

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

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