声明:本题来自力扣,点击标题可以跳转到力扣对应题目,本博客是我跟着花花酱的题目清单做题的笔记博客,主要是自己的学习记录。
什么是深拷贝
深拷贝就是在根据原来的对象,创建一个新的对象,而且这个对象的属性或者说数据都一样,但是两个并不相等,也互不影响。
感觉有一种,把一个人全部的肉体和记忆都克隆出来,但是他们后序的生活是互不影响的,两个人只在克隆那一瞬间完全相似,但是克隆体已经是完全独立的人了,可以这么理解。
有关深拷贝的相关科普文,自行百度搜索。
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);
}
}