86 lines
2.9 KiB
JavaScript
86 lines
2.9 KiB
JavaScript
/**
|
||
* // Definition for a _Node.
|
||
* function _Node(val, neighbors) {
|
||
* this.val = val === undefined ? 0 : val;
|
||
* this.neighbors = neighbors === undefined ? [] : neighbors;
|
||
* };
|
||
* https://leetcode.cn/problems/clone-graph/?envType=study-plan-v2&envId=top-interview-150
|
||
*/
|
||
|
||
/**
|
||
* @param {_Node} node
|
||
* @return {_Node}
|
||
*/
|
||
const cloneGraph = function (node) {
|
||
|
||
};
|
||
|
||
// eslint-disable-next-line no-underscore-dangle, no-unused-vars
|
||
function _Node(val, neighbors) {
|
||
this.val = val === undefined ? 0 : val;
|
||
this.neighbors = neighbors === undefined ? [] : neighbors;
|
||
}
|
||
|
||
/*
|
||
只给了我们一个连通图的一个节点,叫我们克隆整个图,根据两图图的定义,从这个节点出发我们能到达途中的任意一个节点(顶点),
|
||
所以我们只需要遍历所有的neighbor,然后顺着邻居继续遍历邻居即可遍历整个图,但是这里有一个问题,就是如果通过邻居到达了
|
||
自己,或者邻居的邻居,是自己的邻居,就会发生循环,这里就遇到使用一种数据结果来缓存已经遍历过的邻居,当再次遇到它时跳过就行。
|
||
|
||
抽象过程:你需要统计小王家人,你只认识小王,于是题通过小王认识了它的爸爸,妈妈,把他们加入到统计表,然后小王的爸爸向你介绍了
|
||
它的妹妹,同时小王向你介绍了它的姑姑,但是你发现这两个人是同一个人,所以你只统计了一次,最后你就获得了所有和小王有关的人。
|
||
*/
|
||
function f1(node) {
|
||
const visited = new Map(); // 储存原节点,和克隆节点的映射
|
||
/**
|
||
*
|
||
* @param {*} node 需要克隆的节点
|
||
* @returns 返回克隆的节点
|
||
*/
|
||
function clone(node) {
|
||
if (!node) return node;
|
||
|
||
// 如果这个节点之前克隆过,直接返回其克隆节点
|
||
if (visited.has(node)) return visited.get(node);
|
||
|
||
// 创建这个节点的克隆节点
|
||
const cloneNode = new _Node(node.val, []);
|
||
|
||
// node与cloneNode建立映射
|
||
visited.set(node, cloneNode);
|
||
|
||
// 为克隆节点克隆邻居节点
|
||
for (const neighbor of node.neighbors) {
|
||
cloneNode.neighbors.push(clone(neighbor));
|
||
}
|
||
return cloneNode;
|
||
}
|
||
|
||
return clone(node);
|
||
}
|
||
|
||
/*
|
||
思路和上面一致但是使用广度优先遍历
|
||
*/
|
||
function f2(node) {
|
||
if (!node) return node;
|
||
|
||
const visited = new Map();
|
||
const queue = [node]; // 用于广度遍历
|
||
const cNode = new _Node(node.val, []);
|
||
visited.set(node, cNode); // 克隆第一个节点,将其存入visited
|
||
|
||
while (queue.length > 0) {
|
||
const n = queue.shift();
|
||
// 遍历这个节点的所有邻居,如果没有访问过将其clone,并加入visited
|
||
for (const neighbor of n.neighbors) {
|
||
if (!visited.has(neighbor)) {
|
||
visited.set(neighbor, new _Node(neighbor.val, []));
|
||
queue.push(neighbor);
|
||
}
|
||
visited.get(n).neighbors.push(visited.get(neighbor));
|
||
}
|
||
}
|
||
|
||
return cNode;
|
||
}
|