Java 从元素列表创建固定大小的非重复排列列表

Java 从元素列表创建固定大小的非重复排列列表,java,permutation,Java,Permutation,我有一个对象列表M:=[a,B,C,…Z],我想创建一个新的列表N,其中包含这些对象的非重复固定大小“f”排列 因此N将是(对于f=2)[[A,B],[A,C],…],但不应包含类似[A,A]的重复,如果设置了[A,B],则应忽略[B,A] 我发现了像Guavas“PowerSet”这样的东西,但这对我没有帮助,因为它不能“裁剪”成固定大小 我希望我正确地陈述了我的问题 f应始终为2 基于此,我做了以下工作: private Set<List<Object>> combi

我有一个对象列表
M:=[a,B,C,…Z]
,我想创建一个新的列表N,其中包含这些对象的非重复固定大小“
f
”排列

因此N将是
(对于f=2)[[A,B],[A,C],…]
,但不应包含类似
[A,A]
的重复,如果设置了
[A,B]
,则应忽略
[B,A]

我发现了像
Guavas
PowerSet
”这样的东西,但这对我没有帮助,因为它不能“裁剪”成固定大小

我希望我正确地陈述了我的问题

f应始终为2

基于此,我做了以下工作:

private Set<List<Object>> combineObjects(List<Object> M) {
    boolean[] used = new boolean[M.size()];
    return generateObjectCombinations(M, 0, 0, used);
}

private Set<List<Object>> generateObjectCombinations(
    List<Object> M,
    int start,
    int curLen,
    boolean[] used
) {
    Set<List<Object>> returnSet = new HashSet<>();
    if (curLen == 2) {
        List<Object> data = newArrayList();
        for (int i = 0; i < M.size(); i++) {
            if (used[i]) {
                data.add(M.get(i));
            }
        }
        returnSet.add(data);
        return returnSet;
    }
    if (start == M.size()) {
        return Collections.emptySet();
    }
    used[start] = true;
    returnSet.addAll(generateObjectCombinations(M, start + 1, curLen + 1, used));
    used[start] = false;
    returnSet.addAll(generateObjectCombinations(M, start + 1, curLen, used));
    return returnSet;
}
专用集合组合对象(列表M){
boolean[]used=新的boolean[M.size()];
返回GenerateObject组合(M,0,0,已使用);
}
专用集GenerateObject组合(
列表M,
int start,
int curLen,
使用布尔[]
) {
Set returnSet=newhashset();
if(curLen==2){
列表数据=newArrayList();
对于(int i=0;i
这是工作,但我想知道是否有一个“更清洁”的解决方案。我想消除布尔数组

不,这不是我的家庭作业。也许我只是太累了,应该去度假

编辑 根据@azro的回答,我对代码进行了如下重构:

List<List<Object>> combinations = new ArrayList<>();
List<Object> M = new ArrayList<>();

for (int i = 0; i < M.size(); i++) {
    Object outerM = M.get(i);

    for (int j = i; j < M.size(); j++) {
        Object innerM = M.get(j);
        if (innerM.equals(outerM)) {
            continue;
        }
        combinations.add(Lists.newArrayList(outerM, innerM));
    }
}
列表组合=新的ArrayList();
列表M=新的ArrayList();
对于(int i=0;i
甚至更好

List<List<Object>> combinations = new ArrayList<>();
List<Object> M = new ArrayList<>();

for (int i = 0; i < M.size(); i++) {
    Object outerM = M.get(i);

    for (int j = (i + 1); j < M.size(); j++) {
        Object innerM = M.get(j);
        combinations.add(Lists.newArrayList(outerM, innerM));
    }
}
列表组合=新的ArrayList();
列表M=新的ArrayList();
对于(int i=0;i
我真的应该去度个长假。谢谢@azro

因为你没有写“f应该总是2”作为开头,我写了一个解决方案,它适用于
f>=1
,所以这里是方法和使用方法:

public static void main(String[] args) {
        List<String> letter = Arrays.asList("A", "B", "C", "D", "E");
        List<String> res = new ArrayList<>();
        res.addAll(letter);
        int size = 2;

        for (int i = 1; i < size ; i++) {
            res = addLetter(res, letter);   //add a letter to all
        }

        res.forEach(p -> System.out.println(p));
}

public static List<String> addLetter(List<String> already, List<String> letters) {
    List<String> res = new ArrayList<>();

    for (String al : already) {
        for (String let : letters) {
            if (!al.contains(let)) {
                res.add(al + let);
            }
        }
    }
    return res;
}
publicstaticvoidmain(字符串[]args){
列表字母=数组;
List res=new ArrayList();
addAll(信件)决议;
int size=2;
对于(int i=1;iSystem.out.println(p));
}
公共静态列表addLetter(列表已存在,列表字母){
List res=new ArrayList();
for(字符串al:已存在){
for(字符串let:字母){
如果(!al.包含(let)){
res.add(al+let);
}
}
}
返回res;
}

如果“f应始终为2”,则只需:

public static void main(String[] args) {
    List<String> letters = Arrays.asList("A", "B", "C", "D", "E");
    List<String> res = new ArrayList<>();

    for (String al : letters) {
        for (String let : letters) {
            if (!al.contains(let)) {
                res.add(al + let);
            }
        }
    }
    res.forEach(p -> System.out.println(p));
}
publicstaticvoidmain(字符串[]args){
列表字母=数组;
List res=new ArrayList();
用于(字符串al:字母){
for(字符串let:字母){
如果(!al.包含(let)){
res.add(al+let);
}
}
}
res.forEach(p->System.out.println(p));
}

我不确定这是否是最好的解决方案,但这里有:

static HashSet<HashSet<String>> getCombinations(HashSet<HashSet<String>> s, int f)
{
    if(f == 1)
        return s;
    HashSet<HashSet<String>> newSet = new HashSet<HashSet<String>>();
    for (HashSet<String> ss : s)
    {
        for(String elm : A)
        {
            if(ss.contains(elm))
                continue;
            HashSet<String> sss = (HashSet<String>)ss.clone();
            sss.add(elm);
            newSet.add(sss);
        }
    }
    return getCombinations(newSet, f-1);
}
静态HashSet getcombines(HashSet s,int f)
{
如果(f==1)
返回s;
HashSet newSet=新HashSet();
for(哈希集ss:s)
{
对于(弦榆树:A)
{
if(ss.contains(elm))
继续;
HashSet sss=(HashSet)ss.clone();
sss.add(elm);
新闻集添加(sss);
}
}
返回getcompositions(新闻集,f-1);
}
用法:

String[] A = {"A", "B", "C", "D", "E"};
public static void main(String[] args)
{
    int f = 3;
    HashSet<HashSet<String>> set = new HashSet<>();
    for(String s : A)
    {
        HashSet<String> ss = new HashSet<>();
        ss.add(s);
        set.add(ss);
    }
    System.out.println(getCombinations(set, f));
}
String[]A={“A”、“B”、“C”、“D”、“E”};
公共静态void main(字符串[]args)
{
int f=3;
HashSet=newhashset();
for(字符串s:A)
{
HashSet ss=新的HashSet();
ss.添加(s);
集合。添加(ss);
}
System.out.println(getcompositions(set,f));
}

不是真的-你的问题是什么?展示一些你做过的事情,我知道你的意思。这很容易。。你所需要的只是一个包含字母的数组和一个Foreach循环中的Foreach循环。很抱歉,Stackoverflow不是用来做作业的。请证明你在发布你的问题之前确实尝试了一些东西…看下面,我的当然适用于f=2,但也适用于f=3,4,…谢谢@azro解决了我的问题。