Java 如何在飞行中进行组合数学

Java 如何在飞行中进行组合数学,java,algorithm,combinations,combinatorics,cartesian-product,Java,Algorithm,Combinations,Combinatorics,Cartesian Product,我有一个非常奇怪的问题,有一些限制,使它很难解决。我有一个列表,我想把这些列表中的所有项目组合起来。每个项目都有一个名称和一个值。以下是一个例子: 主要清单: 清单01: 项目01:名称:名称01,值:值01 项目02:名称:名称02,值:value02 清单02: 项目01:名称:名称03,值:值03 清单03: 项目01:名称:名称04,值:值04 项目02:名称:名称05,值:值05 最终结果应如下所示: 一些名单: 项目01:name01:value01,名称03:va

我有一个非常奇怪的问题,有一些限制,使它很难解决。我有一个列表,我想把这些列表中的所有项目组合起来。每个项目都有一个名称和一个值。以下是一个例子:

主要清单:

  • 清单01:
    • 项目01:名称:名称01,值:值01
    • 项目02:名称:名称02,值:value02
  • 清单02:
    • 项目01:名称:名称03,值:值03
  • 清单03:
    • 项目01:名称:名称04,值:值04
    • 项目02:名称:名称05,值:值05
最终结果应如下所示:

一些名单:

  • 项目01:name01:value01,名称03:value03,名称04:value04
  • 项目02:名称02:value02,名称03:value03,名称04:value04
  • 项目03:name03:value03,名称03:value03,名称04:value04
  • 项目04:name01:value01,名称03:value03,名称04:value05
  • 项目05:名称02:value02,名称03:value03,名称04:value05
  • 项目06:名称03:value03,名称03:value03,名称04:value05
新列表中几乎包含了类似于哈希映射的项

约束条件如下所示:

  • 我无法收集到新的列表并将它们混合,因为这些列表可能会很快变得相当大
  • 我正在使用一些类似api的观察者,所以我需要让观察者尽快了解结果,这样我就不会占用太多内存
  • 换句话说,这个组合生成器可能会提供X个列表,每个列表可能包含N个项目,我必须在不使用太多内存的情况下生成它们的组合

    我不希望一次使用超过5个列表,但我希望使算法尽可能地适应代码更改

    我正在用java解决这个问题,但该算法在其他语言中也应该同样有效,因为它可能会被翻译

    你有什么想法和建议吗

    提前谢谢


    另外,我认为递归不会很好地工作。我一直在考虑使用while循环和一些嵌套循环,但是很难想象这应该如何工作。

    创建一个索引数组,每个列表一个索引,怎么样?可以通过依次对每个列表执行get()来读取当前组合。每个索引都将为零,然后前进到下一个有效的组合

    index[0]++;
    if (index[0] >= list[0].size()) {
        index[0] = 0;
        index[1]++;
        if (index[1] >= list[1].size()) {
            ...
        }
    }
    

    (将嵌套的if转换为迭代,作为读者的练习。)

    为什么不制作一个hashmap呢

    Map<String,Map<String,String>> mainMap = new HashMap<String,Map<String,String>>();
    
    for(List l : lists) {
        for(Data d : l) {
            String item = d.item;
            String name = d.name;
            String value = d.value;
    
            Map<String,String> itemMap = mainMap.get(item);
            if(item == null) {
                itemMap = new HashMap<String,String>(); 
                mainMap.put(item,itemMap);
            }
            itemMap.put(name,value);
        }
    } 
    
    Map mainMap=newhashmap();
    对于(列表l:列表){
    用于(数据d:l){
    String item=d.item;
    字符串名称=d.name;
    字符串值=d.value;
    Map itemMap=mainMap.get(项目);
    如果(项==null){
    itemMap=newhashmap();
    mainMap.put(item,itemMap);
    }
    itemMap.put(名称、值);
    }
    } 
    
    稍后,您希望获得给定名称的所有值,而不管是哪一项

    List<String> getValuesForName(String name) {
        List<String> list = new LinkedList<String>();
        for(Map<String,String map : mainMap) {
            String value = map.get(name);
            if(value != null) list.add(value);
        }
        return list;
    }
    
    列出getValuesForName(字符串名称){
    列表=新建LinkedList();
    
    对于(Map您不需要使用任何内存来解决此问题。可以从数学上获得列表的第n个元素,而无需创建整个组合。这是解释的,所以这是笛卡尔积,您要的是

    假设有3个列表,包含2个、1个和3个元素。您将以2*1*3组合=6结束。(摘要:a*b*…*i)

    现在从0到5取6个数字

    void getCombiFor (int i, List <List <Integer>> li) 
    {
         if (li.length > 0) 
         { 
            int idx = i % li.get (0).size ();        
            System.out.print (li.get (0).get(idx));                 
            getCombiFor (i - idx, li.remove (0));
         } 
         System.out.println ();
    }   
    // pseudocodeline:
    List li = List (List ('a', 'b'), List ('c'), List ('d', 'e', 'f'))
    for (int i = 0; i < 6; ++i) 
    {
         getCombiFor (i, li);
    }
    

    每个索引都从0开始,obvs。您的示例不太清楚,并且包含一个错误。我可以推荐3个包含2、1和3个元素的列表((a、b)(c)(d、e、f))。这将导致6个解决方案(笛卡尔积或叉积)。阅读a:=(name01,value01)如果你愿意的话。但是你的例子在某个列表项03:n3v3-n3v3-中有两次。这不是故意的,是吗?
    Lists = ((a,b), (c), (d,e,f))
    acd
    bcd
    acf
    bcf
    ace
    bce