1、問題分析
題目鏈接: https://leetcode-cn.com/problems/clone-graph/
本質上就是一個圖的遍歷問題,首先用一個hashmap
存儲節點的值和節點本身的對應關係(根據源節點創建),然後仍然根據源節點,將之前 hashmap
中沒有賦值的neighbors
給賦值。最後輸出第一個節點即可。讀者可以直接看源代碼。我基本每一個重要步驟都註釋了。
2、問題解決
筆者以C++方式解決。
#include "iostream"
using namespace std;
#include "algorithm"
#include "vector"
#include "map"
class Node {
public:
int val;
vector<Node *> neighbors;
Node() {
val = 0;
neighbors = vector<Node *>();
}
Node(int _val) {
val = _val;
neighbors = vector<Node *>();
}
Node(int _val, vector<Node *> _neighbors) {
val = _val;
neighbors = _neighbors;
}
};
class Solution {
private:
// 定義頂點數目
static const int MAXV = 101;
// 用於複製節點時 標記是否訪問
bool vis[MAXV] = { false };
// 用於給neighbors賦值時, 標記是否訪問
bool vis1[MAXV] = { false };
// 將節點的值和節點對應
map<int, Node *> val_map;
public:
Node *cloneGraph(Node *node) {
if (node == NULL) {
return NULL;
}
dfs_create_node(node);
dfs(node);
return val_map[1];
}
/**
* 根據 node 創建節點,並對應到map中
* 本質就是圖的遍歷
* @param node
*/
void dfs_create_node(Node *node) {
// 標記該節點已經訪問
vis[node->val] = true;
// 根據源節點生成新節點(先賦值,不更新 neighbors ,
// 即 neighbors 暫時爲空,因爲此時的 neighbors 節點可能還沒有new 出來)
val_map[node->val] = new Node(node->val);
// 根據鄰接表對圖進行深搜
for (int i = 0; i < node->neighbors.size(); ++i) {
// 獲取下一個訪問節點的值
int v = node->neighbors[i]->val;
// 如果之前沒有訪問過該節點
if (!vis[v]) {
// 根據 node->neighbors[i]) 創建節點,並對應到map中
dfs_create_node(node->neighbors[i]);
}
}
}
/**
* 根據源節點 給 map 中的 neighbors 賦值
* @param node
*/
void dfs(Node *node) {
//標記該節點已經訪問
vis1[node->val] = true;
// 取出map 中的節點,根據 源節點 node 的值標記 該節點的鄰接表 即 neighbors ,
// 注意這裏的 neighbors 存儲的仍然是 map 中的節點
for (int i = 0; i < node->neighbors.size(); ++i) {
val_map[node->val]->neighbors.push_back(val_map[node->neighbors[i]->val]);
}
// 和上面一樣深搜
for (int i = 0; i < node->neighbors.size(); ++i) {
int v = node->neighbors[i]->val;
if (!vis1[v]) {
dfs(node->neighbors[i]);
}
}
}
};
int main() {
// 創建節點
Node *pNode1 = new Node(1);
Node *pNode2 = new Node(2);
Node *pNode3 = new Node(3);
Node *pNode4 = new Node(4);
// 給節點建立鄰接表
pNode1->neighbors.push_back(pNode2);
pNode1->neighbors.push_back(pNode4);
pNode2->neighbors.push_back(pNode1);
pNode2->neighbors.push_back(pNode3);
pNode3->neighbors.push_back(pNode2);
pNode3->neighbors.push_back(pNode4);
pNode4->neighbors.push_back(pNode1);
pNode4->neighbors.push_back(pNode3);
Solution *pSolution = new Solution;
Node *pNode = pSolution->cloneGraph(pNode1);
cout << pNode1 << endl;
system("pause");
return 0;
}
運行結果
有點菜,有時間再優化一下。
3、總結
書上的代碼直接運行絕大部分是對的,但是總有一些軟件的更新使得作者無能爲力。之前的API是對的,但是之後就廢棄了或修改了是常有的事。所以我們需要跟蹤源代碼。這只是一個小小的問題,如果沒有前輩的無私奉獻,很難想象我們自己一天能學到多少內容。感謝各位前輩的辛勤付出,讓我們少走了很多的彎路!
點個贊再走唄!歡迎留言哦!