题目:给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的深度拷贝。
这里需要注意的是深度拷贝和浅度拷贝的区别。前度拷贝是直接复制,拷贝的是原始对象的引用地址,在队中仍然公用一块内存;深度拷贝是为新对象在堆中重新分配一个内存,所以对新对象的操作不会影响旧对象。
思路:这个是剑指上的复杂链表复制的题目。网上代码1的思路是首先复制原始链表中的节点,把原始节点和复制节点放在一个哈希表中,然后设置各个节点随机指向的节点,因为之前将两者都存放在哈希表中,因此很容易可以找到对应的节点。空间复杂度O(n),时间复杂度O(n).
代码1:网上找的大神的代码。原文链接:https://blog.csdn.net/u012249528/article/details/47111467
public class Solution {
public RandomListNode copyRandomList(RandomListNode head) {
HashMap<RandomListNode, RandomListNode> newMap=new HashMap<>();
//进行第一次遍历 将节点存入哈希表
RandomListNode cur=head;
while(cur!=null)
{
RandomListNode newNode=new RandomListNode(cur.label);
newMap.put(cur, newNode);
cur=cur.next;
}
cur=head;
while(cur!=null)
{
RandomListNode node=newMap.get(cur);
node.next=newMap.get(cur.next);
node.random=newMap.get(cur.random);
cur=cur.next;
}
return newMap.get(head);
}
}
代码2:这个是剑指中提供的代码。思路和代码3一致,但是写法稍微不同。
剑指中的代码我还是有些看不懂,还是看下面的执行最快的代码。
剑指中的这个代码在leetcode中运行不对,先把代码写在这里:
public RandomListNode Clone2(RandomListNode pHead) {
if(pHead == null)
return null;
RandomListNode head = new RandomListNode(pHead.label) ;
RandomListNode temp = head ;
while(pHead.next != null) {
temp.next = new RandomListNode(pHead.next.label) ;
if(pHead.random != null) {
temp.random = new RandomListNode(pHead.random.label) ;
}
pHead = pHead.next ;
temp = temp.next ;
}
return head ;
}
代码3:执行时间是1秒的代码:
这个代码的思路和剑指中的思路相同,首先复制原始链表中的节点并将复制后的节点放在原始节点的后面,之后处理随机节点,因为前一步的设置可知随机节点后的节点就是复制后的节点,最后将复制后的链表与原始链表拆分出来就可以了。
以下代码完成了在不用辅助空间的情况下实现O(n)的时间效率。主要分为三步。首先第一步,根据原始链表的节点创建对应的节点,这次把复制的节点放在原始节点之后;第二步,设置复制出来的节点;第三步,把长链表拆分成两个链表。
以下这个代码我自己重写就是错的。。。。。。。
public class Solution {
public RandomListNode copyRandomList(RandomListNode head) {
if (head == null) {
return null;
}
//每个节点后插入一个相同节点
for (RandomListNode cur = head; cur != null; ) {
RandomListNode node = new RandomListNode(cur.label);
node.next = cur.next;
cur.next = node;
cur = node.next;
}
//完成random指针
for (RandomListNode cur = head; cur != null; ) {
if (cur.random != null) {
cur.next.random = cur.random.next;
}
cur = cur.next.next;
}
//分拆链表
RandomListNode newHead = new RandomListNode(0);
for (RandomListNode cur = head, newCur = newHead; cur != null; ) {
//生成新链表
newCur.next = cur.next;
newCur = newCur.next;
//保证原链表顺序
cur.next = cur.next.next;
cur = cur.next;
}
return newHead.next;
}
}