图和链表的深拷贝

声明:本题来自力扣,点击标题可以跳转到力扣对应题目,本博客是我跟着花花酱的题目清单做题的笔记博客,主要是自己的学习记录。

什么是深拷贝

深拷贝就是在根据原来的对象,创建一个新的对象,而且这个对象的属性或者说数据都一样,但是两个并不相等,也互不影响。
感觉有一种,把一个人全部的肉体和记忆都克隆出来,但是他们后序的生活是互不影响的,两个人只在克隆那一瞬间完全相似,但是克隆体已经是完全独立的人了,可以这么理解。

有关深拷贝的相关科普文,自行百度搜索。

133.克隆图

根据题目要求:这是一个无向连通图

  • 无向
    无向说明一个节点可以访问邻节点,那它的邻节点也可以反过来访问它:
    就像下面这个一样A节点可以访问B节点,反之B节点也可以访问A节点

在这里插入图片描述

  • 连通
    连通说明一个节点可以访问所有的节点

题目要求对一个无向连通图进行深拷贝,有深度优先和广度优先两种方法

1.深度优先

图解深度优先的过程:
在这里插入图片描述
在拷贝的过程中,我们需要先拷贝当前节点,然后再去拷贝它的邻节点。
又因为是无向连通图,所以防止重复拷贝,我们需要使用哈希表来记录节点的拷贝状态,实现代码如下

class Solution {
    public Map<Node,Node> map = new HashMap<>();
    public Node cloneGraph(Node node) {
        if(node == null){
            return node;
        }
        //查看当前节点是否拷贝,如果拷贝过了,接返回该节点
        if(map.containsKey(node)){
            return map.get(node);
        }
        //如果没有拷贝就拷贝当前节点,并放入map
        Node cloneNode = new Node(node.val, new ArrayList<Node>());
        map.put(node,cloneNode);
        //遍历相邻节点,并拷贝
        for(Node neighbor : node.neighbors){
            cloneNode.neighbors.add(cloneGraph(neighbor));
        }
        return cloneNode;
    }
}

2.广度优先

图解广度优先过程:
在这里插入图片描述
广度优先一般要使用到队列实现,先将题目给我们的节点的邻节点入队,然后遍历队
和上面一样防止重复拷贝,就需要使用哈希表来记录每个节点拷贝情况

class Solution {
    public Node cloneGraph(Node node) {
        if(node == null){
            return node;
        }

        Map<Node, Node> map = new HashMap<>();
        LinkedList<Node> queue = new LinkedList<>();

        //将节点放进队列中
        queue.add(node);
        //克隆当前节点,并放入地图中
        Node cloneNode = new Node(node.val, new ArrayList<Node>());
        map.put(node,cloneNode);
        //对队列进行遍历
        while(!queue.isEmpty()){
            Node n = queue.remove();
            //遍历邻节点
            for(Node neighbor : n.neighbors){
            	//如果不在map中就克隆,并且入队
                if(!map.containsKey(neighbor)){
                    map.put(neighbor, new Node(neighbor.val, new ArrayList<Node>()));
                    queue.add(neighbor);
                }
                //如果已经克隆了就加入到深拷贝的相应的邻节点中
                map.get(n).neighbors.add(map.get(neighbor));
            }
        }

        return cloneNode;
    }
}

138.复制带随机指针的链表

在普通的链表中,一般就只有一个next指针,指向下一个链表节点,而这个带随机指针的链表就是:带有两个指针,一个是next指向下一个节点,另外一个是random随机指向一个节点(如下图)
在这里插入图片描述

这个题目只要将节点、next指针、random指针分批克隆

代码 如下

class Solution {
    public Map<Node, Node> map = new HashMap<>();
    public Node copyRandomList(Node head) {
        if(head == null){
            return head;
        }

        if(!map.containsKey(head)){
      		//先克隆当前节点
            Node cloneHead = new Node(head.val);
            map.put(head, cloneHead);
            //克隆next指针
            cloneHead.next = copyRandomList(head.next);
            //克隆random节点
            cloneHead.random = copyRandomList(head.random);
        }

        return map.get(head);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值