leetcode——链表操作——138.复制带随机指针的链表

思路

方法1:建立原——新映射关系,遍历到某节点时,不仅创建该节点,还创建其后的 random 节点

方法2:将新节点放在原节点后面,然后再分离

  1. 思路:不是一次遍历,对每个进行处理的时候再创建新节点,而是两次遍历,第一次创建所有新节点,第二次再修改指向;不然必须修改源节点

  2. 关键!!!将链表分离的方法(将间隔节点连在一起,分成两个链),既得到克隆链,又还原原链子(不还原原链子会报错)

题目

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。

构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。

例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random --> y 。

返回复制链表的头节点。

用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:

val:一个表示 Node.val 的整数。
random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为  null 。
你的代码 只 接受原链表的头节点 head 作为传入参数。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/copy-list-with-random-pointer
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

//方法1:建立原——新映射关系,遍历到某节点时,不仅创建该节点,还创建其后的 random 节点

//方法2:将新节点放在原节点后面,然后再分离

//方法1:先遍历一遍,建立所有新节点,并用 next 链接起来,第二遍遍历建立 random 关系
//方法1解法:
class Solution {
    public Node copyRandomList(Node head) {
        Map<Node,Node> map=new HashMap<>();
        Node node=head;
        Node newHead=new Node(-1);
        Node pre=newHead;
        while(node!=null){
            Node newNode=new Node(node.val);
            pre.next=newNode;
            pre=pre.next;
            map.put(node,newNode);
            node=node.next;
        }

        node=head;
        
        while(node!=null){
            //Node newNode=map.get(node);
            if(node.random!=null){
                map.get(node).random=map.get(node.random);
            }
            node=node.next;
        }
        return newHead.next;
    }
}

//方法2:遍历一遍,为所有创建新节点,新节点放在原节点后面,第二遍遍历建立 random关系,第三遍遍历将两个链表拆开
class Solution {
    public Node copyRandomList(Node head) {
        //方法2:
        //思路:不是一次遍历,对每个进行处理的时候再创建新节点,而是两次遍历,第一次创建所有新节点,第二次再修改指向;不然必须修改源节点
        //关键!!!将链表分离的方法(将间隔节点连在一起,分成两个链),既得到克隆链,又还原原链子(不还原原链子会报错)
        if(head==null)  return head;

        Node node=head;
        while(node!=null){
            Node newNode=new Node(node.val);
            newNode.next=node.next;
            node.next=newNode;
            node=node.next.next;
        }

        node=head;
        while(node!=null){
            if(node.random!=null)   node.next.random=node.random.next;
            node=node.next.next;
        }
        node=head;
        Node cloneNode=head.next;
        Node pre=new Node(-1);
        // while(node!=null){
        //     Node temp=node.next;
        //     pre.next=temp;
        //     node.next=null;
        //     node=temp.next;
        //     pre=pre.next;
        // }
        //关键!!!将链表分离的方法(将间隔节点连在一起,分成两个链),既得到克隆链,又还原原链子(不还原原链子会报错)
        while(node.next!=null){
            Node temp=node.next;
            node.next=node.next.next;
            node=temp;
        }

        return cloneNode;


        


    }
}

/*
//自己写的,速度很差
class Solution {
    public Node copyRandomList(Node head) {
        if(head==null) return null;
        
        Map<Node,List<Node>> mapTo=new HashMap<>();
        Node p=head;
        while(p!=null){

            if(p.random!=null){ 
                List<Node> l;
                if(mapTo.containsKey(p.random)){
                    l=mapTo.get(p.random);
                }else{
                    l=new LinkedList<Node>();
                }
                l.add(p);
                mapTo.put(p.random,l);
                
            }
            p=p.next;
        }

        Node r=new Node(head.val);
        
        Node pre=new Node(-1);
        Node q=pre;
        p=head;
        Map<Node,Node> have=new HashMap<Node,Node>();
        while(p!=null){
            Node newNode=new Node(p.val);
            q.next=newNode;
            q=q.next;

            have.put(p,newNode);
            if(have.containsKey(p.random)){
                newNode.random=have.get(p.random);
            }

            List<Node> fromList=mapTo.get(p);
            if(fromList!=null){
                for(Node from:fromList){
                    if(have.containsKey(from)){
                        have.get(from).random=newNode;
                    }     
                }
            }
            
            p=p.next;
        }

        return pre.next;


    }
}

*/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值