该题克隆图类似二叉树的遍历,是从根节点遍历叶节点。
复制思路:是dfs遍历原节点node,建立HashMap<Node,Node>原节点到克隆节点的映射,然后根据原节点,new出新节点,建立节点之间关系。map是用来做递归的截止条件map.containsKey(node)就之间返回当前节点的clone节点。(就是图中绿色节点)
DFS:
//方法签名
public Node cloneGraph(Node node) {
if (node == null) {
return null;
}
HashMap<Node, Node> map = new HashMap<>();
return dfs(node, map);
}
// void方法问题
// 1、如果dfs中只考虑下一个节点。如何结束递归,如果map存在为准,那么最叶节点重复不会加入到它的父节点关系中。
// 2、将node,newNode加入map之后,如果只看当前节点的话直接return了
// public void dfs(Node node, HashMap<Node, Node> map) {
// // 无返回值的dfs,一般用来在边界条件中更新全部变量的。
// for (Node n : node.neighbors) {
// if (!map.containsKey(n)) {
// Node n_add = new Node(n.val);
// // 连接图的边
// map.get(node).neighbors.add(n_add);
// // 将原图的边与新建的边对应起来,表示n已被访问
// map.put(n, n_add);
// dfs(n, map);
// }
// }
// }
// 只看当前节点是否重复出现
public Node dfs(Node node, HashMap<Node, Node> map) {
if (map.containsKey(node)) {
// 被clone过直接返回
return map.get(node);
}
// 复制当前节点
Node clone = new Node(node.val);
// 表示node已被clone过
map.put(node, clone);
// clone邻居节点
for (Node n : node.neighbors) {
clone.neighbors.add(dfs(n, map));
}
return clone;
}
BFS:思路都是挨个clone节点,被clone过的直接返回被clone过的节点。
public Node BFS(Node node) {
if (node == null) {
return null;
}
HashMap<Node, Node> map = new HashMap<>();
Deque<Node> q = new LinkedList<>();
// clone
Node root = new Node(node.val);
map.put(node, root);
// 入队
q.offer(node);
while (!q.isEmpty()) {
Node tmp = q.poll();
// clone邻居节点
for (Node n : tmp.neighbors) {
// 如果没被复制过,clone然后保存
if (!map.containsKey(n)) {
Node clone = new Node(n.val);
map.put(n, clone);
q.offer(n);
}
// 与父节点连接
map.get(tmp).neighbors.add(map.get(n));
}
}
return root;
}