【问题标题】:Recreating LinkedList of pointers from list of pointers从指针列表重新创建指针的 LinkedList
【发布时间】:2020-10-26 11:15:41
【问题描述】:

我有一个随机“指针”列表

  • "A,B,C,D,E,F"

它们属于N个不同的链表

  • “A->C->D”、“B->E”、“F”

我可以从指针中获得的唯一信息是“孩子”知道“父母”,但反之则不然。

我目前将它们分类到各自的链表中的实现如下。

如果我能得到一些关于优化下面代码的建议或者我的方法是错误的,我将不胜感激。

        for (Pointer i: listOfPointers) {
            if (!i.hasParent())
                // no parent, its a root node
                rootNodes.add(i.getId());
            else {
                // parent -> child
                parentChild.put(i.getParent().getId(),i.getId());
            }
        }
        // iterate through the head/roots
        for (String i : rootNodes) {
            LinkedList<String> templist = new LinkedList<>();
            LinkedList<Map<String,String>> temp = new LinkedList<>();
            String tempnow = i;
            //construct our linked list, start by the head and getting the child until we have nothing left
            do{
                if (templist.size() == 0)
                    System.out.println("Parent - " + tempnow);
                else
                    System.out.println("Child - " + tempnow);
                templist.add(tempnow);
                if (parentChild.containsKey(tempnow))
                    tempnow = parentChild.get(tempnow);
                else
                    break;
            }while(true);
            linkedListHashMap.put(i, templist);
        }

【问题讨论】:

    标签: java pointers


    【解决方案1】:

    我将创建一个Map,它通过其父级映射每个Pointer(实际上是边缘的Map),除了需要单独存储的根节点。之后,您可以通过重复遍历图直到找不到进一步的映射来重构List

    public Collection<List<Pointer>> group(Collection<Pointer> pointers) {
        if(pointers.isEmpty()) {
            return Collections.emptyList();
        }
    
        List<Pointer> roots = new ArrayList<>();
        Map<Pointer, Pointer> parents = new HashMap<>(pointers.size());
    
        for(Pointer pointer : pointers) {
            if(pointer.hasParent()) {
                parents.put(pointer.getParent(), pointer);
            } else {
                roots.add(pointer);
            }
        }
    
        List<List<Pointer>> results = new ArrayList<>(roots.size());
    
        for(Pointer root : roots) {
            List<Pointer> list = new LinkedList<>();
            list.add(root);
    
            Pointer current = parents.get(root);
            while(current != null) {
                list.add(current);
                current = parents.get(current);
            }
    
            results.add(list);
        }
    
        return results;
    }
    

    对于您给出的输入:

    Pointer a = new Pointer("A");
    Pointer c = new Pointer("C", a);
    Pointer d = new Pointer("D", c);
    
    Pointer b = new Pointer("B");
    Pointer e = new Pointer("E", b);
    
    Pointer f = new Pointer("F");
    
    Collection<Pointer> pointers = Arrays.asList(a, b, c, d, e, f);
    Collection<List<Pointer>> grouped = group(pointers);
    // result: A -> C-> D ; B -> E ; F 
    

    【讨论】:

    • 谢谢,我想我现有的解决方案已经足够优化了,除了使用地图的变化。
    • 您还可以创建已知大小的集合(参见代码)。对于Map,有pointers.size() 个节点减去根的数量。但是,由于我预计只有几个根,这应该是一个很好的估计。 result 这个大小也是已知的。
    【解决方案2】:

    虽然有一些简单的解决方案可以在原始列表的顶部构建额外的数据结构,但我认为找到一个需要恒定数量的额外内存的解决方案会很有趣,比如这个:

    boolean sorted = false;
    while (!sorted) {
      sorted = true;
      for (Element element: elements) {
        Element parent = element.parent;
        if (parent != null) {
          Element grandParent = parent.parent;
          if (grandParent != null && parent.value > grandParent.value) {
            element.parent = grandParent;
            parent.parent = grandParent.parent;
            grandParent.parent = parent;
            sorted = false;
          }
        }
      }
    }
    
    // Now the tails of all lists are sorted, only the heads
    // (first elements) may be misplaced
    
    for (Element element : elements) {
      Element parent = element.parent;
      Element child = null;
      while (parent != null && element.value > parent.value) {
        if (child != null)
          child.parent = parent;
        element.parent = parent.parent;
        parent.parent = element;
        child = parent;
        parent = element.parent;
      }
    }
    

    这个想法是,当所有列表都排序后,每个元素可能不会大于其父元素。因此,如果我们看到A-&gt;B-&gt;C-&gt;...B &gt; C,那么我们将这个片段重新排列为A-&gt;C-&gt;B-&gt;...。我们这样做直到没有这样的片段需要重新排列,这意味着所有列表的尾部都已排序,只有头部(第一个元素)可能放错了位置。

    现在我们寻找类似于A-&gt;B-&gt;... 的片段,其中A &gt; B。由于只有头可能放错了位置,而A显然放错了,那么A是一个头,即没有A的孩子。所以我们可以从A开始遍历列表,找到这个列表的位置应该放置A,并将A移到那里,无需将A的孩子更新为A保证没有孩子。

    这是一个在随机数据上运行的示例:

    Original:
    78->77->2->39->67->78->98->
    86->30->71->90->86->97->98->30->88->31->67->19->36->5->57->16->
    7->16->19->12->74->98->55->60->38->25->2->37->45->92->3->52->24->43->41->84->95->73->77->19->91->15->29->60->
    17->94->25->
    34->80->
    51->
    68->23->1->89->5->17->67->35->97->26->57->38->
    89->84->
    58->
    8->5->87->43->8->
    72->60->
    41->49->28->92->84->
    41->33->15->8->55->40->16->58->13->86->35->16->77->71->
    53->13->
    
    After the first loop:
    78->2->39->67->77->78->98->
    86->5->16->19->30->30->31->36->57->67->71->86->88->90->97->98->
    7->2->3->12->15->16->19->19->24->25->29->37->38->41->43->45->52->55->60->60->73->74->77->84->91->92->95->98->
    17->25->94->
    34->80->
    51->
    68->1->5->17->23->26->35->38->57->67->89->97->
    89->84->
    58->
    8->5->8->43->87->
    72->60->
    41->28->49->84->92->
    41->8->13->15->16->16->33->35->40->55->58->71->77->86->
    53->13->
    
    After the second loop:
    84->89->
    5->8->8->43->87->
    2->39->67->77->78->78->98->
    13->53->
    17->25->94->
    28->41->49->84->92->
    8->13->15->16->16->33->35->40->41->55->58->71->77->86->
    60->72->
    34->80->
    51->
    5->16->19->30->30->31->36->57->67->71->86->86->88->90->97->98->
    58->
    1->5->17->23->26->35->38->57->67->68->89->97->
    2->3->7->12->15->16->19->19->24->25->29->37->38->41->43->45->52->55->60->60->73->74->77->84->91->92->95->98->
    

    【讨论】:

    • 嗨,这个“功能”的重点不是物理上的“排序”,因为没有什么要排序的。问题是从节点的原始指针重建链表
    • 那么函数的输出是什么?它是否应该为每个指针分配一个列表 ID,因此属于同一列表的指针具有相同的列表 ID,而属于不同列表的指针具有不同的列表 ID?还是应该输出一个集合的集合,其中每个集合对应一个链表并包含该链表中的所有指针?
    • 后者将是必需的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    • 2015-03-03
    • 1970-01-01
    • 2021-04-09
    • 2014-02-13
    • 2016-07-30
    • 1970-01-01
    相关资源
    最近更新 更多