给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的 深拷贝。
我们用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
val:一个表示 Node.val 的整数。
random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。
方法一:根据题目中提到的索引信息,想到的方法。原节点→索引→新节点
private Map<Node, Integer> nodeToIndex; // 原节点与索引的映射 private Map<Integer, Node> indexToNode; // 索引与新节点的映射 public Node copyRandomList(Node head) { if (head == null) { return null; } // 构建nodeToIndex nodeToIndex = new HashMap<Node, Integer>(); int key = 0; nodeToIndex.put(head, key); Node nextNode = head.next; while(nextNode != null) { nodeToIndex.put(nextNode, ++key); nextNode = nextNode.next; } // 生成newHead(包含next关系),并构建indexToNode indexToNode = new HashMap<Integer, Node>(); key = 0; Node newHead = new Node(head.val); Node curNode = newHead; nextNode = head.next; while(nextNode != null) { Node tempNode = new Node(nextNode.val); curNode.next = tempNode; indexToNode.put(key++, curNode); curNode = curNode.next; nextNode = nextNode.next; } curNode.next = null; indexToNode.put(key, curNode); // 根据nodeToIndex与indexToNode,获取newHead链表的random信息 curNode = newHead; while(head != null) { if (head.random != null) { key = nodeToIndex.get(head.random); curNode.random = indexToNode.get(key); } curNode = curNode.next; head = head.next; } return newHead; }
方法二:先建立新节点,直接构建旧节点与新节点的映射关系,不考虑中间索引信息。原节点→新节点
private Map<Node, Node> map;
public Node copyRandomList(Node head) { if (head == null) { return null; } // 构建原节点与copy节点的映射map map = new HashMap<>(); Node node = head; while(node != null) { Node copyNode = new Node(node.val); map.put(node, copyNode); node = node.next; } // 根据map获取next和random。 copy节点的next/random是原节点的next/random所对应的value值。 Node copyHead = map.get(head); node = head; while (node != null) { map.get(node).next = map.get(node.next); map.get(node).random = map.get(node.random); node = node.next; } return copyHead; }