Copy List with Random Pointer (复制有随机指针的链表)
A linked list is given such that each node contains an additional random pointer which could point to any node in the list or null.
Return a deep copy of the list.
题目意思是让我们复制一个链表,这个链表的特别之处在于除了有next指针外,还有一个random指针,具体见RandomListNode的定义代码:
/**
* Definition for singly-linked list with a random pointer.
* class RandomListNode {
* int label;
* RandomListNode next, random;
* RandomListNode(int x) { this.label = x; }
* };
*/
那么此题的最直接的解题思路就是先不管random指针,复制一个一般的链表,这个只需要我们遍历一遍原链表,复制一波即可。考虑到还有个random指针,所以采用HashMap来储存原链表节点和新的复制的节点。在第二次遍历hashmap的时候再将random指针的信息复制给新链表,最后返回新链表的头节点即可。在实际代码中,链表类题目一般我会new一个dummy节点,让dummy.next指向头节点,这样做的好处是不用考虑原链表是否为null。具体代码如下:
public class Solution {
/**
* @param head: The head of linked list with a random pointer.
* @return: A new head of a deep copy of the list.
*/
public RandomListNode copyRandomList(RandomListNode head) {
// write your code here
Map<RandomListNode, RandomListNode> map = new HashMap<>();
RandomListNode dummy = new RandomListNode(0);
RandomListNode node = dummy;
RandomListNode headCopy = head;
while(head != null){
RandomListNode newNode = new RandomListNode(head.label);
map.put(head, newNode);
node.next = newNode;
node = node.next;
head = head.next;
}
node = dummy.next;
while(node != null){
if(headCopy != null){
node.random = map.get(headCopy.random);
}
headCopy = headCopy.next;
node = node.next;
}
return dummy.next;
}
}
假设原链表1->2->3, 1的random指向3,2,3的random为null。
注意点:刚开始new了一个dummy node,然后将dummy node的内存地址赋值给声明的node节点,将原链表的head节点的内存地址赋值给声明的headCopy节点。之后第一个while循环就是要复制除了random指针的其余信息,包含label,next。首先判断原链表的head节点是否为空,不为空创建一个newNode,将head的值给它,然后将head和newNode对象都放入map中。注意此时head对象的label,next,random都不为空,而newNode对象的next和random一定是null。然后将newNode的内存地址赋值给node.next,则此时dummy node的next也被修改,因为dummy node和node目前是指向同一个内存地址。这样dummy node也就记录了原链表的第一个值,即dummy.next.label和dummy.next有值。然后就可以将node.next的内存地址赋值给node,这样就修改了node所记录的内存地址,从而继续遍历时dummy node不受影响。随后的循环每次将新的内存地址赋值给node.next,再修改node指向的内存地址。图示如下:
之后做的事情就比较简单了,取出原链表中的random信息赋值给新链表即可。