如何创建保持相同顺序的链接列表的深层副本
Posted
技术标签:
【中文标题】如何创建保持相同顺序的链接列表的深层副本【英文标题】:How to create deep copy of Linked List that maintain same order 【发布时间】:2017-12-18 23:21:55 【问题描述】:我在一次求职面试中被问到以下我无法弄清楚的问题。您将获得以下节点元素的链接列表:
class Node
int value;
Node next; // points to next element in list
Node random; // points to one random element of list
假设您有这些节点的链接列表(例如 20 个节点),其中“next”指向下一个元素,“random”指向列表的另一个元素(意思是,可以指向一个特定但随机选择的元素在列表中)。即,第一个元素的“随机”可以指向节点#5,节点第二个元素的随机可以指向节点#9,等等。
问题:如何创建一个全新的链接列表,它是此节点列表的深层副本,但“随机”和“下一个”保持相同的顺序和相同的链接?
换句话说,如果使用这两个指针中的任何一个遍历这个新列表,则遍历顺序将是相同的。
一些人引用的另一个主题将通过默认克隆克隆相同的指针,这不会解决这个挑战。
【问题讨论】:
How to clone ArrayList and also clone its contents?的可能重复 【参考方案1】:循环所有节点并将所有节点放入HashMap
,其中节点为键,新节点实例为值。
Map<Node, Node> nodeMap = new HashMap<>();
...
nodeMap.put(currentNode, new Node();
现在您再次遍历所有“旧”节点,只需循环 node.next
并为每个节点复制节点,以便您引用映射的值而不是旧节点本身。
Node newNode = nodeMap.get(currentNode);
newNode.value = currentNode.value;
newNode.next = nodeMap.get(currentNode.next);
newNode.random = nodeMap.get(currentNode.random);
之后你应该有一个没有重复实例的精确副本。
【讨论】:
聪明的解决方案。【参考方案2】:import java.util.*;
public class Solution
HashMap<RandomListNode, RandomListNode> map = new HashMap<RandomListNode, RandomListNode>();
public RandomListNode copyRandomList(RandomListNode head)
if (head == null)
return null;
if (map.containsKey(head))
return map.get(head);
RandomListNode node = new RandomListNode(head.label);
map.put(head, node);
node.next = copyRandomList(head.next);
node.random = copyRandomList(head.random);
return node;
【讨论】:
【参考方案3】:在网上搜索了一段时间后,我找到了这个问题的答案。相当棘手。他们提出了这个主要解决方案:
复制每个节点,即复制每个节点,并将其插入到列表中 为所有新创建的节点复制随机指针 将列表分成两个请看这里:http://www.programcreek.com/2012/12/leetcode-copy-list-with-random-pointer/
【讨论】:
我们真的需要在同一个列表中插入重复的节点吗?我们不能创建一个新的头并从原始列表中复制下一个指针吗?然后再次迭代它以复制随机指针。这行得通吗?以上是关于如何创建保持相同顺序的链接列表的深层副本的主要内容,如果未能解决你的问题,请参考以下文章
如何合并多个 observables 并保持顺序和最大并发?
如何在c#中保持内部顺序的同时将2个排序的列表合并到一个随机列表中