题目描述:
一种特殊的单链表节点类描述如下
class Node
int value;
Node next;
Node rand;
Node(int val){
value = val;}
}
rand指针是单链表节点结构中新增的指针,rand可能指向链表中的任意一个节点,也可能指向null。给定一个由Node节点类型组成的无环单链表的头节点head,请实现一个函数完成这个链表的复制,并返回复制的新链表的头节点。
[要求]时间复杂度0(N),额外空间复杂度(1)
解法一:借助哈希表实现
用hashMap的键值对特征来实现每一个节点的克隆,再根据老节点的 next 指针和 random 指针来将克隆节点组成新链表。
代码:
public Node copyRandomList(Node head) {
HashMap<Node,Node> map = new HashMap<>();
//将每一个节点克隆一份
Node p = head;
while(p != null){
map.put(p,new Node(p.val));
p = p.next;
}
//根据旧节点(key)来将克隆节点组成新的链表
p = head;
while(p != null){
map.get(p).next = map.get(p.next);
map.get(p).random = map.get(p.random);
p = p.next;
}
//返回克隆头节点
return map.get(head);
}
解法二:原链表上进行节点克隆,不借助哈希表,空间复杂度 O(1)
通过克隆节点的位置特征(克隆节点都在老节点后边)省去了哈希表
代码:
public Node copyRandomList(Node head) {
if(head == null){
return null;
}
//克隆节点
Node p = head;
Node next = null;
while(p != null){
next = p.next;
p.next = new Node(p.val);
p.next.next = next;
p = next;
}
//根据老节点匹配克隆节点的random指针
p = head;
while(p != null){
p.next.random = p.random != null ? p.random.next : null;
p = p.next.next;
}
//将克隆节点组成新链表
Node res = head.next;
p = head;
Node curCopy = null;//此节点为了增强代码可读性,可以不用定义
while(p != null){
next = p.next.next;
curCopy = p.next;
//恢复老链表
p.next = next;
curCopy.next = next != null ? next.next : null;
p = next;
}
return res;
}
力扣题目链接:力扣
解法二力扣提交时出现的问题:
Next pointer of node with label 7 from the original list was modified
要将老链表也恢复