题目过长,不复制了
简单来说就是给个图,然后让完全复制一份,不能引用原来的结点,就是不能直接return原来的node,也不能新创建一个node把临边赋值一份就算完。
分析:
这直接dfs一遍或者bfs一遍就行了,第一种思路是先创建结点,然后用一个哈希表去把原结点和复制结点一一对应,在跑一边,把边连上即可。
另一种思路是同时复制边和点。
/*
// Definition for a Node.
class Node {
public int val;
public List<Node> neighbors;
public Node() {
val = 0;
neighbors = new ArrayList<Node>();
}
public Node(int _val) {
val = _val;
neighbors = new ArrayList<Node>();
}
public Node(int _val, ArrayList<Node> _neighbors) {
val = _val;
neighbors = _neighbors;
}
}
*/
class Solution {
Map<Node, Node> map = new HashMap<>();
public Node cloneGraph(Node node) {
if (node == null) return null; // lc特色,非得卡我一次
// dfs先把点都复制下来
dfs(node);
for (Node p : map.keySet()) {
// 枚举哈希表的每一个点,将他的边复制给新的点
Node copy = map.get(p);
// p是原点 copy是新的点
for (Node neighbor : p.neighbors) {
// 枚举原点的邻点
// map.get(neighbor)是原点的邻点的复制点,即应该被链接的那个点
// 复制点去链接这个邻接点
copy.neighbors.add(map.get(neighbor));
}
}
return map.get(node);
}
void dfs(Node node) {
// 创建新的结点并且做映射
map.put(node, new Node(node.val));
for (Node p : node.neighbors) {
// 枚举旁边的点,如果没创建过,就遍历回去,如果不判断就会死循环
if (!map.containsKey(p))
dfs(p);
}
}
}
/*
// Definition for a Node.
class Node {
public int val;
public List<Node> neighbors;
public Node() {
val = 0;
neighbors = new ArrayList<Node>();
}
public Node(int _val) {
val = _val;
neighbors = new ArrayList<Node>();
}
public Node(int _val, ArrayList<Node> _neighbors) {
val = _val;
neighbors = _neighbors;
}
}
*/
class Solution {
Map<Node, Node> map = new HashMap<>();
public Node cloneGraph(Node node) {
if (node == null) return null;
// 先把跟放进来,这步是个特殊处理,dfs里面没办法写了
map.put(node, new Node(node.val));
dfs(node);
return map.get(node);
}
void dfs(Node node) {
for (Node p : node.neighbors) {
// 如果当前结点的邻接点还没有复制过的话
if (!map.containsKey(p)) {
// 1. 复制进去,并且打个标记,这里的map其实就是一个标记作用的,完全可以想办法替代掉。
// 但是上面的代码就不行了,因为没有map就无法找到复制点了
map.put(p, new Node(p.val));
// 同时建立边的关系
map.get(node).neighbors.add(map.get(p));
// 搜索
dfs(p);
} else {
// 如果已经被复制过了,那加一条反向边即可
map.get(node).neighbors.add(map.get(p));
}
}
}
}