给出一个链表,每个节点包含一个额外增加的随机指针可以指向链表中的任何节点或空的节点。
返回一个深拷贝的链表。
挑战
可否使用O(1)的空间
解题思路1:
利用HashMap。分为两步:
1、顺序复制原始链表上的每个节点,不包含random指针。同时将原链表节点与复制链表节点的对应关系保存到map中,方便后续random指针的对应。
2、遍历map,先找到原节点random的指向,然后根据map关系就能找到复制节点random的指向。
/**
* Definition for singly-linked list with a random pointer.
* class RandomListNode {
* int label;
* RandomListNode next, random;
* RandomListNode(int x) { this.label = x; }
* };
*/
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 pHead) {
// write your code here
//存储原链表节点与复制链表节点的对应关系
Map<RandomListNode, RandomListNode> map = new HashMap<>();
//普通复制原始链表的每个节点,除了随机指针
RandomListNode head = cloneNodes(pHead, map);
//利用map找到随机指针的定位
for(RandomListNode oldNode : map.keySet())
map.get(oldNode).random = map.get(oldNode.random);
return head;
}
private RandomListNode cloneNodes(RandomListNode pHead, Map<RandomListNode, RandomListNode> map){
RandomListNode dummy = new RandomListNode(0);
RandomListNode node = dummy;
while(pHead != null){
RandomListNode temp = new RandomListNode(pHead.label);
map.put(pHead, temp);
node.next = temp;
node = node.next;
pHead = pHead.next;
}
return dummy.next;
}
}
解题思路2:
1、在原链表的每个节点后面拷贝出一个新的节点
2、依次给新的节点的随机指针赋值
3、将奇偶节点分开连接,即获得了复制好的链表
时间复杂度O(N)
对应函数copyNext(head);
对应函数:copyRandom(head);
对应函数:splitList(head);
/**
* Definition for singly-linked list with a random pointer.
* class RandomListNode {
* int label;
* RandomListNode next, random;
* RandomListNode(int x) { this.label = x; }
* };
*/
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
if(head == null)
return null;
//在原链表的每个节点后面拷贝出一个新的节点
copyNext(head);
//依次给新的节点的随机指针赋值
copyRandom(head);
//将奇偶节点分开连接,即获得了复制好的链表
return splitList(head);
}
private void copyNext(RandomListNode head){
while(head != null){
RandomListNode newNode = new RandomListNode(head.label);
newNode.next = head.next;
head.next = newNode;
newNode.random = null;
head = head.next.next;
}
}
private void copyRandom(RandomListNode head){
while(head != null){
RandomListNode newNode = head.next;
//当head.random指向null时需特殊处理,防止空指针异常
if(head.random != null)
newNode.random = head.random.next;
else
newNode.random = null;
head = head.next.next;
}
}
private RandomListNode splitList(RandomListNode head){
RandomListNode newNode = head.next;
RandomListNode temp = newNode;
while(head != null){
head.next = temp.next;
head = temp.next;
//当head到尾端时需特殊处理,防止空指针异常
if(head != null){
temp.next = head.next;
temp = head.next;
}else{
temp.next = null;
}
}
return newNode;
}
}