草庐IT

java - N个有序元素的组合

coder 2024-01-07 原文

我有一组 K 个元素,我需要创建一个 N 个有序元素的组合。
例如,如果 K=1 并且我有 {X1, emptyset} 和 n = 2 那么我有一个有序的对,我需要这样做:

示例 1:

 ({},{})  
 ({X1},{}), ({},{X1})  
 ({X1},{X1})  

请注意,我需要按以下顺序获取元素:首先是节点为 0 的元素作为两对之和,其次是节点为 1 的元素,ecc

我的想法是制作初始集的部分集,一次添加一个元素,但我失去了理智。有什么建议么?我需要在 Java 中执行此操作。

编辑 1: 换句话说,我需要创建一个 Hasse 图: http://en.wikipedia.org/wiki/Hasse_diagram

其中每个节点都是部分集合的一个元素,偏序函数是对所有子集的包含,如下所示:

例子2:

ni = (S1i,S2i) C nj = (S1j,S2j) 仅当 S1i C S1j AND S21 C s2j

编辑 2:@RONALD:

如果对于集合 S = {1, 2} 和​​ n =2,我有 K=2,我需要这个输出:

 level0: ({}, {})  
 level1: ({1}, {}); ({2}, {}); ({}, {1}); ({}, {2})  
 level2: ({1,2}, {}); ({1}, {1}); ({1}, {2}); ({2}, {1}); ({2}, {2}); ({}, {1,2});   
 [..]

级别之间的顺序很重要,例如:

如果在level1我有

 ({1}, {}); ({2}, {}); ({}, {1}); ({}, {2})  

 ({}, {2}); ({}, {1}); ({2}, {}); ({1}, {}); 

是一样的。但重要的是,在第 2 级,我拥有第 2 级的所有超集,并且在示例 2

中解释了超集

编辑 3:
如果我的集合是 S= {x,y,z} 并且每个节点只有一个集合,则结果(从底部开始)是这样的: http://upload.wikimedia.org/wikipedia/commons/e/ea/Hasse_diagram_of_powerset_of_3.svg

如果我有 S={1,2} 并且每次点头设置两个,结果是这样的(感谢 Ronald 提供的图表):
http://www.independit.de/Downloads/hasse.pdf

编辑4:

因为这是一个超指数问题,所以我的想法是:我一次计算一个级别(在有序模式下!)并根据一些规则我修剪一个节点及其所有超集。另一个停止规则可能是在某个级别停止。对于此规则,必须以有序的方式直接计算组合,而不是计算所有组合然后重新排序。

编辑5:

Marco13 的代码工作正常,我做了一些修改:

  • 使用函数 PowerSet,因为它有助于仅组合集合 S 的 K 个元素(为此我只需要获取 powerset 的第一个 tot 元素)。

现在算法完成了所有工作,但我需要加快速度。有什么办法可以并行计算吗?这样一种使用Map Reduce(Apache hadoop实现)范式的方式?

package utilis;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class HasseDiagramTest4
{
    public static void main(String[] args)
    {
        int numberOfSetsPerNode = 3;

        List<Integer> set = Arrays.asList(1, 2, 3, 4, 5,6);
        List<Set<Integer>> powerSet = computePowerSet(set);
        powerSet = KPowerSet(powerSet, 3);

        List<List<Set<Integer>>> prunedNodes = 
            new ArrayList<List<Set<Integer>>>();
        List<Set<Integer>> prunedNode = new ArrayList<Set<Integer>>();

        HashSet<Integer> s = new HashSet<Integer>();
        HashSet<Integer> s_vuoto = new HashSet<Integer>();
        s.add(1);
        s.add(2);
        prunedNode.add(s);
        prunedNode.add(s_vuoto);
        prunedNode.add(s);

       prunedNodes.add(prunedNode);

        compute(ordina(powerSet), numberOfSetsPerNode, prunedNodes);
    }

    private static <T> HashMap<Integer, List<Set<T>>> ordina(List<Set<T>> powerSet) {

        HashMap<Integer, List<Set<T>>> hs = new HashMap<Integer, List<Set<T>>>();

        for(Set<T> l: powerSet)
        {
            List<Set<T>> lput = new  ArrayList<Set<T>>();
            if(hs.containsKey(l.size()))
            {
                lput = hs.get(l.size());
                lput.add(l);
                hs.put(l.size(), lput);
            }
            else
            {
                lput.add(l);
                hs.put(l.size(), lput); 
            }

        }

        return hs;
    }

    private static <T> List<Set<T>> KPowerSet(List<Set<T>> powerSet, int k)
    {
        List<Set<T>> result = new ArrayList<Set<T>>();

        for(Set<T>s:powerSet)
        {
            if(s.size() <= k)
            {
                result.add(s);
            }
        }
        return result;
    }

    private static <T> List<Set<T>> computePowerSet(List<T> set)
    {
        List<Set<T>> result = new ArrayList<Set<T>>();
        int numElements = 1 << set.size();
        for (int j=0; j<numElements; j++)
        {
            Set<T> element = new HashSet<T>();
            for (int i = 0; i < set.size(); i++)
            {
                long b = 1 << i;
                if ((j & b) != 0)
                {
                    element.add(set.get(i));
                }
            }
            result.add(element);
        }
        return result;
    }

    private static List<Integer> createList(int numberOfElements)
    {
        List<Integer> list = new ArrayList<Integer>();
        for (int i=0; i<numberOfElements; i++)
        {
            list.add(i+1);
        }
        return list;
    }

    private static <T> void compute(
            HashMap<Integer, List<Set<T>>> powerSet, int numberOfSetsPerNode,
        List<List<Set<T>>> prunedNodes)
    {
        Set<List<Set<T>>> level0 = createLevel0(numberOfSetsPerNode);
        System.out.println("Level 0:");
        print(level0);

        Set<List<Set<T>>> currentLevel = level0;
        int level = 0;
        while (true)
        {
            Set<List<Set<T>>> nextLevel = 
                createNextLevel(currentLevel, powerSet, prunedNodes);
            if (nextLevel.size() == 0)
            {
                break;
            }

            System.out.println("Next level: "+nextLevel.size()+" nodes");
            print(nextLevel);

            currentLevel = nextLevel;
            level++;
        }
    }

    private static <T> Set<List<Set<T>>> createLevel0(int numberOfSetsPerNode)
    {
        Set<List<Set<T>>> level0 = 
            new LinkedHashSet<List<Set<T>>>();
        List<Set<T>> level0element = new ArrayList<Set<T>>();
        for (int i=0; i<numberOfSetsPerNode; i++)
        {
            level0element.add(new LinkedHashSet<T>());
        }
        level0.add(level0element);
        return level0;
    }

    private static <T> List<Set<T>> getNext(Set<T> current, HashMap<Integer, List<Set<T>>> powerSet)
    {
        ArrayList<Set<T>> ritorno = new ArrayList<Set<T>>(); 
        int level = current.size();
        List<Set<T>> listnext = powerSet.get(level+1);

        if(listnext != null)
        {
            for(Set<T> next: listnext)
            {
                if(next.containsAll(current))
                {
                    ritorno.add(next);
                }
            }
        }

        return ritorno;
    }


    private static <T> Set<List<Set<T>>> createNextLevel(
        Set<List<Set<T>>> currentLevel, HashMap<Integer, List<Set<T>>> powerSet,
        List<List<Set<T>>> prunedNodes)
    {
        Set<List<Set<T>>> nextLevel = new LinkedHashSet<List<Set<T>>>();

        //Per ogni nodo del livello corrente
        for (List<Set<T>> currentLevelElement : currentLevel)
        {
            //Per ogni insieme del nodo preso in considerazione
            for (int i=0; i<currentLevelElement.size(); i++)
            {
                List<Set<T>> listOfnext = getNext (currentLevelElement.get(i), powerSet);


                for (Set<T> element : listOfnext)
                {
                    List<Set<T>> nextLevelElement = copy(currentLevelElement);
                    Set<T> next = element;
                    nextLevelElement.remove(i);
                    nextLevelElement.add(i, next);

                    boolean pruned = false;
                    for (List<Set<T>> prunedNode : prunedNodes)
                    {
                        if (isSuccessor(prunedNode, nextLevelElement))
                        {
                            pruned = true;
                        }
                    }
                    if (!pruned)
                    {
                        nextLevel.add(nextLevelElement);
                    }
                    else
                    {
                        System.out.println("Pruned "+nextLevelElement+ " due to "+prunedNodes);
                    }
                }
            }
        }
        return nextLevel;
    }

    private static <T> boolean isSuccessor(
        List<Set<T>> list, List<Set<T>> successor)
    {
        for (int i=0; i<list.size(); i++)
        {
            Set<T> set = list.get(i);
            Set<T> successorSet = successor.get(i);
            //System.out.println("Successor:" + successorSet + "pruned:" + set);
            if (!successorSet.containsAll(set))
            {
                return false;
            }
        }
        return true;
    }

    private static <T> List<Set<T>> copy(List<Set<T>> list)
    {
        List<Set<T>> result = new ArrayList<Set<T>>();
        for (Set<T> element : list)
        {
            result.add(new LinkedHashSet<T>(element));
        }
        return result;
    }

    private static <T> void print(
        Iterable<? extends Collection<? extends Collection<T>>> sequence)
    {
        for (Collection<? extends Collection<T>> collections : sequence)
        {
            System.out.println("    "+collections);
        }
    }


}

最佳答案

经过 4 次编辑和大量讨论后,这个应用程序的目标慢慢变得更加清晰。的确,人们不得不考虑一种适当的形式化,但它最终似乎并不那么困难。

与我的第一个答案 (https://stackoverflow.com/a/22092523) 相比,这个新答案从上一层迭代计算下一层(其核心 createNextLevel 只是 10 行代码)。

compute 方法中,“EDIT4”中要求的剪枝可以集成到 while 循环中。

编辑:评论中还有更多请求。整合他们。但这变得荒谬了。 Um den Rest kannst du dich selbst kümmern。

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

public class HasseDiagramTest2
{
    public static void main(String[] args)
    {
        int numberOfElements = 2;
        int numberOfSetsPerNode = 2;

        List<Integer> list = createList(numberOfElements);

        List<List<Set<Integer>>> prunedNodes = 
            new ArrayList<List<Set<Integer>>>();
        List<Set<Integer>> prunedNode = new ArrayList<Set<Integer>>();
        prunedNode.add(Collections.singleton(1));
        prunedNode.add(Collections.singleton(1));
        prunedNodes.add(prunedNode);

        compute(list, numberOfSetsPerNode, prunedNodes);
    }

    private static List<Integer> createList(int numberOfElements)
    {
        List<Integer> list = new ArrayList<Integer>();
        for (int i=0; i<numberOfElements; i++)
        {
            list.add(i+1);
        }
        return list;
    }

    private static <T> void compute(
        List<T> elements, int numberOfSetsPerNode,
        List<List<Set<T>>> prunedNodes)
    {
        Set<List<Set<T>>> level0 = createLevel0(numberOfSetsPerNode);
        System.out.println("Level 0:");
        print(level0);

        Set<List<Set<T>>> currentLevel = level0;
        int level = 0;
        while (true)
        {
            Set<List<Set<T>>> nextLevel = 
                createNextLevel(currentLevel, elements, prunedNodes);
            if (nextLevel.size() == 0)
            {
                break;
            }

            System.out.println("Next level: "+nextLevel.size()+" nodes");
            print(nextLevel);

            currentLevel = nextLevel;
            level++;
        }
    }

    private static <T> Set<List<Set<T>>> createLevel0(int numberOfSetsPerNode)
    {
        Set<List<Set<T>>> level0 = 
            new LinkedHashSet<List<Set<T>>>();
        List<Set<T>> level0element = new ArrayList<Set<T>>();
        for (int i=0; i<numberOfSetsPerNode; i++)
        {
            level0element.add(new LinkedHashSet<T>());
        }
        level0.add(level0element);
        return level0;
    }

    private static <T> Set<List<Set<T>>> createNextLevel(
        Set<List<Set<T>>> currentLevel, List<T> elements,
        List<List<Set<T>>> prunedNodes)
    {
        Set<List<Set<T>>> nextLevel = new LinkedHashSet<List<Set<T>>>();
        for (List<Set<T>> currentLevelElement : currentLevel)
        {
            for (int i=0; i<currentLevelElement.size(); i++)
            {
                for (T element : elements)
                {
                    List<Set<T>> nextLevelElement = copy(currentLevelElement);
                    Set<T> next = nextLevelElement.get(i);
                    boolean changed = next.add(element);
                    if (!changed)
                    {
                        continue;
                    }
                    boolean pruned = false;
                    for (List<Set<T>> prunedNode : prunedNodes)
                    {
                        if (isSuccessor(prunedNode, nextLevelElement))
                        {
                            pruned = true;
                        }
                    }
                    if (!pruned)
                    {
                        nextLevel.add(nextLevelElement);
                    }
                    else
                    {
//                        System.out.println(
//                            "Pruned "+nextLevelElement+
//                            " due to "+prunedNodes);
                    }
                }
            }
        }
        return nextLevel;
    }

    private static <T> boolean isSuccessor(
        List<Set<T>> list, List<Set<T>> successor)
    {
        for (int i=0; i<list.size(); i++)
        {
            Set<T> set = list.get(i);
            Set<T> successorSet = successor.get(i);
            if (!successorSet.containsAll(set))
            {
                return false;
            }
        }
        return true;
    }

    private static <T> List<Set<T>> copy(List<Set<T>> list)
    {
        List<Set<T>> result = new ArrayList<Set<T>>();
        for (Set<T> element : list)
        {
            result.add(new LinkedHashSet<T>(element));
        }
        return result;
    }

    private static <T> void print(
        Iterable<? extends Collection<? extends Collection<T>>> sequence)
    {
        for (Collection<? extends Collection<T>> collections : sequence)
        {
            System.out.println("    "+collections);
        }
    }


}

关于java - N个有序元素的组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22071804/

有关java - N个有序元素的组合的更多相关文章

  1. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  2. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  3. ruby - 在哈希的键数组中追加元素 - 2

    查看我的Ruby代码:h=Hash.new([])h[0]=:word1h[1]=h[1]输出是:Hash={0=>:word1,1=>[:word2,:word3],2=>[:word2,:word3]}我希望有Hash={0=>:word1,1=>[:word2],2=>[:word3]}为什么要附加第二个哈希元素(数组)?如何将新数组元素附加到第三个哈希元素? 最佳答案 如果您提供单个值作为Hash.new的参数(例如Hash.new([]),完全相同的对象将用作每个缺失键的默认值。这就是您所拥有的,那是你不想要的。您可以改用

  4. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  5. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  6. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

    这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

  7. 【Java 面试合集】HashMap中为什么引入红黑树,而不是AVL树呢 - 2

    HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候

  8. 「Python|Selenium|场景案例」如何定位iframe中的元素? - 2

    本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决

  9. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  10. java - 为什么 ruby​​ modulo 与 java/other lang 不同? - 2

    我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.

随机推荐