leetcode笔记——138复制带随机指针的列表&剑指35

题目:给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。

要求返回这个链表的深度拷贝

这里需要注意的是深度拷贝和浅度拷贝的区别。前度拷贝是直接复制,拷贝的是原始对象的引用地址,在队中仍然公用一块内存;深度拷贝是为新对象在堆中重新分配一个内存,所以对新对象的操作不会影响旧对象。

思路:这个是剑指上的复杂链表复制的题目。网上代码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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值