当前位置: 首页 > 知识库问答 >
问题:

以所有可能的方式将列表拆分为n个子列表

戚飞虎
2023-03-14

我想用Java中所有可能的方法将一个列表拆分为给定数量的n个子列表。

例如,[1,2,3,4]其中n=3将包括以下列表(但不是一个完整的解决方案-完成将需要更多的空间):

([], [], [1,2,3,4])
([],[1],[2,3,4])
([],[1,2],[3,4])
([],[1,2,3],[4])
([],[1,2,3,4],[])
([1],[2,3,4], [])
([1],[2,3],[4])
([2,3],[4],[1])
([4],[],[1,2,3])
...

我适应了另一个类似的问题的解决方案(以所有可能的方式将列表分割成两个子列表),但它只适用于创建2个子列表的列表,我正在努力掌握如何实现灵活而不是硬编码的子列表数量。

这是我的密码:

public List<List<EGroup>> permutation(List<E> list) {
        List<List<E>> sublists = new ArrayList<List<E>>();
        for (int i = 0; i <= list.size(); i++) {
          permutationSplit(list, sublists, i, new ArrayList<E>(), 0);
        }

        List<List<EGroup>> listOfEGroupPairs = new ArrayList<List<EGroup>>();
       
        for (List<E> subList : sublists) {
            List<E> listCopy = new ArrayList<E>(list);
            listCopy.removeAll(subList);
            EGroup e1 = new EGroup(subList);
            EGroup e2 = new EGroup(listCopy);   
            List<EGroup> egr = new ArrayList<EGroup>();
            egr.add(e1);
            egr.add(e2);
            listOfEGroupPairs.add(egr);
        }
        
        return listOfEGroupPairs;
    }

   
    public void permutationSplit(List<E> list, List<List<E>> subLists, int sublistSize, List<E> currentSubList,
          int startIndex) {
        if (sublistSize == 0) {
          subLists.add(currentSubList);
        } else {
          sublistSize--;
          for (int i = startIndex; i < list.size(); i++) {
            List<E> newSubList = new ArrayList<E>(currentSubList);
            newSubList.add(list.get(i));
            permutationSplit(list, subLists, sublistSize, newSubList, i + 1);
          }
        }
    }

我需要创建n个数的EGroup对象添加到listOfEGroupPair,而不是硬编码的2,但如何总是获得不同大小的子列表的正确数量(n)每个循环

共有3个答案

柳奇思
2023-03-14

使用递归。

对于n等于0或负的任务是不可能的。抛出异常或返回子列表列表的空列表。角例:如果n为0且列表为空,您可能会认为子列表的空列表是有效的响应。

如果n为1,那么唯一的解决方案就是整个列表。

n

如果列表的长度为4(例如[1,2,3,4]),则有5个可能的第一个列表。通常有列表。长度1可能的第一个子列表。找到他们。对于每个这样的子列表,进行递归调用,将列表的剩余部分和n-1作为参数传递,以查找从列表的剩余部分生成的子列表的所有可能组合。将每个第一个子列表与剩余子列表的每个组合组合,以形成完整的解决方案。

快乐编码。

PS如草图所示的解决方案将仅按照子列表在原始列表中的顺序生成子列表。因此,解决方案将包括([],[1],[2,3,4])([1],[2,3,4],]),但不包括([4],[1,2,3])。要将最后一个视为单独的解决方案,您还需要找到每个解决方案的所有排列,同时考虑到一些子列表可能是相等的,因此交换它们不会产生不同的解决方案。

仰翰采
2023-03-14

如果我正确理解这个问题,原始列表中的每个元素都可以在任何一个n子列表中结束。这意味着,有n^s可能的子列表(s是原始列表中元素的数量),可以在一个简单的循环中枚举。通过一点模和整数除法,您可以为每个元素获得适当的“桶”,并相应地准备结果。

public <T> List<List<List<T>>> partition(List<T> lst, int n) {
    var result = new ArrayList<List<List<T>>>();
    // k = SUM ( pos of lst[i] * n^i ) 
    for (int k = 0; k < Math.pow(n, lst.size()); k++) {
        // initialize result
        List<List<T>> res = IntStream.range(0, n)
                .mapToObj(i -> new ArrayList<T>())
                .collect(Collectors.toList());
        // distribute elements to sub-lists
        int k2 = k;
        for (int i = 0; i < lst.size(); i++) {
            res.get(k2 % n).add(lst.get(i));
            k2 /= n;
        }
        result.add(res);
    }
    return result;
}
谷良弼
2023-03-14

您有K元素,每个元素都可能属于任何N列表。所以有N^K变体,我们可以将整数值从0映射到N^K-1到像N进制数字系统这样的分布。

另一种方法-递归地将每个元素插入N个列表中。

我可以演示Python代码递归,N-ary的方法,并希望它可以被翻译成Java

def recdistr(K, N, level, ls):
    if level == K:
        print(ls)
    else:
        for i in range(N):
            ls[i].append(level)
            recdistr(K, N, level + 1, ls)   #recursive call with changed list
            ls[i].pop()  #remove last added element to revert list to previous state

K = 4
N = 3
lst = [[] for _ in range(N)]
recdistr(K, N, 0, lst)

def mapdistr(K, N):
    for x in range(N**K):
        t = x
        l = [[] for _ in range(N)]
        for i in range(K):
            id = t % N
            t = t // N   #integer division
            l[id].append(i)
        print(l)

 mapdistr(K, N)
 类似资料:
  • 例如,我有一个可变大小的列表 我想用各种可能的方法把这个列表分成两部分: 我很确定这不是一个未知的问题,可能有一个算法,但是我找不到。此外,这不应使用任何外部库,而应使用简单的语言功能(循环、条件、方法/函数、变量等)在大多数语言中都可以找到。 我用Python写了一个hackish解决方案: 但是,它使用了库功能,总体上不是很好看。

  • 问题内容: 我有这个清单(): 我想要这样的东西: 换句话说,我想使用值作为分隔符将列表拆分为子列表,以获得列表列表()。我正在寻找Java 8解决方案。我已经尝试过,但是我不确定这是我要找的东西。谢谢! 问题答案: 我目前想出的唯一解决方案是实现自己的自定义收集器。 在阅读解决方案之前,我想添加一些有关此的注释。我将这个问题更多地当作编程练习,我不确定是否可以使用并行流来完成。 因此,您必须意识

  • 问题内容: 我有一个ArrayList,我想将其分成n个大小的较小列表,并对每个列表执行一个操作。我目前这样做的方法是 用Java中的ArrayLists实现(任何伪代码都可以) 其中A是列表,n是所需列表的大小 我认为在处理相当大的列表(最大为100万个)时,这种方法会花费太多时间,因此我试图找出哪种方法更有效。 问题答案: 您需要做一些利用List.subList(int,int)视图的事情,

  • 感兴趣的是在同一pyspark数据帧中将列表的这一列拆分为多列的scala-spark实现 给定该数据帧: 我想要一个新的数据帧,它包含分解值并映射到我提供的列名称: 尝试: 但它的格式错误,我不知道如何映射到我的 colNames 列表: 在上面的链接中,python的解决方案是使用列表理解: 但它没有显示如何使用提供的列名列表,因为列名只是列的索引。

  • 问题:如何将列表拆分为两个子列表,其中元素由元素中的选项卡分隔? 上下文:我想读取一个由制表符分隔的文件到Pandas DataFrame中。这些文件看起来像: 列1\t 123 列2\t 列3\t文本 这意味着每行有一列,后面跟着一个选项卡,然后是该列的一个值(有时没有值)。 我的想法是读取文件并将每行保存为列表的元素,然后将列表分成两个,将选项卡前的第一部分作为一个列表,选项卡后的第二部分作为

  • 如何将这列列表拆分为两列? 期望的结果: