LeetCode Clone Graph
class Solution { public: UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) { UndirectedGraphNode *clone = dfs(node); dfs_clear(node); return clone; } UndirectedGraphNode *dfs(UndirectedGraphNode *orgin) { if (orgin == NULL) return NULL; UndirectedGraphNode *clone = get_clone_node(orgin); if (clone != NULL) return clone; // cout<<"cloning node :"<<orgin->label<<endl; int olen = orgin->neighbors.size(); clone = add_clone_node(orgin); for (int i=0; i<olen; i++) { UndirectedGraphNode *nb = orgin->neighbors[i]; clone->neighbors.push_back(dfs(nb)); } return clone; } void dfs_clear(UndirectedGraphNode *node) { UndirectedGraphNode *clone = get_clone_node(node); if (clone == NULL) return; // cout<<"clear node: "<<node->label<<endl; del_clone_node(node); int len = node->neighbors.size(); for (int i=0; i<len; i++) { dfs_clear(node->neighbors[i]); } } UndirectedGraphNode *get_clone_node(UndirectedGraphNode *node) { int len; // cout<<"get info of cloned node : "<<node->label<<endl; if (node == NULL || (len = node->neighbors.size()) < 2 || node->neighbors[len - 2] != NULL) return NULL; return node->neighbors[len - 1]; } UndirectedGraphNode *add_clone_node(UndirectedGraphNode *node) { if (node == NULL) return NULL; // cout<<"append link for cloned node: "<<node->label<<endl; node->neighbors.push_back(NULL); node->neighbors.push_back(new UndirectedGraphNode(node->label)); return node->neighbors.back(); } void del_clone_node(UndirectedGraphNode *node) { if (get_clone_node(node) == NULL) return; // cout<<"del clone link for node:"<<node->label<<endl; node->neighbors.pop_back(); // cloned node addr node->neighbors.pop_back(); // null } };
dfs扫描复制,通过在neighbor数组中加入NULL指针来标记已复制与未复制的节点,同时在NULL项后存储该节点对应的克隆节点,最后将原有节点还原。240ms
类似的可以用一个hash表来存储新节点地址与对应老节点的对应关系,同时进行连接关系的复制。当然两种方法的dfs可以改成bfs,防止栈溢出。
class Solution { private: unordered_map<UndirectedGraphNode*, UndirectedGraphNode*> o2n; public: UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) { o2n.clear(); UndirectedGraphNode *clone = dfs(node); return clone; } UndirectedGraphNode *dfs(UndirectedGraphNode *node) { if (node == NULL) return NULL; unordered_map<UndirectedGraphNode *, UndirectedGraphNode *>::iterator iter = o2n.find(node); if (iter != o2n.end()) return iter->second; UndirectedGraphNode *clone = new UndirectedGraphNode(node->label); o2n.insert(make_pair(node, clone)); int len = node->neighbors.size(); for (int i=0; i<len; i++) { clone->neighbors.push_back(dfs(node->neighbors[i])); } return clone; } };
第二轮:
Clone an undirected graph. Each node in the graph contains a label
and a list of its neighbors
.
OJ's undirected graph serialization:
Nodes are labeled uniquely.
We use#
as a separator for each node, and ,
as a separator for node label and each neighbor of the node.
As an example, consider the serialized graph {0,1,2#1,2#2,2}
.
The graph has a total of three nodes, and therefore contains three parts as separated by #
.
- First node is labeled as
0
. Connect node0
to both nodes1
and2
. - Second node is labeled as
1
. Connect node1
to node2
. - Third node is labeled as
2
. Connect node2
to node2
(itself), thus forming a self-cycle.
Visually, the graph looks like the following:
1 / \ / \ 0 --- 2 / \ \_/
故技重施:
/** * Definition for undirected graph. * struct UndirectedGraphNode { * int label; * vector<UndirectedGraphNode *> neighbors; * UndirectedGraphNode(int x) : label(x) {}; * }; */ // 9:20 class Solution { public: UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) { if (node == NULL) { return NULL; } duplicate(node); clone(node); UndirectedGraphNode* res = node->neighbors.back(); restore(node); return res; } void duplicate(UndirectedGraphNode *node) { if (node == NULL) { return; } int nlen = node->neighbors.size(); if (nlen > 1 && node->neighbors[nlen - 2] == NULL && node->neighbors[nlen - 1]->label == node->label) { // we have duplicated it return; } // we haven't duplicated this node node->neighbors.push_back(NULL); UndirectedGraphNode* tmp = new UndirectedGraphNode(node->label); node->neighbors.push_back(tmp); for (int i=0; i<nlen; i++) { tmp->neighbors.push_back(node->neighbors[i]); } for (int i=0; i<nlen; i++) { duplicate(node->neighbors[i]); } } void clone(UndirectedGraphNode *node) { if (node == NULL) return; int nlen = node->neighbors.size(); UndirectedGraphNode *newNode = node->neighbors.back(); if (nlen <= 2 || node->neighbors[0] != newNode->neighbors[0]) { // already cloned it return; } for (int i=0; i<nlen-2; i++) { newNode->neighbors[i] = newNode->neighbors[i]->neighbors.back(); } for (int i=0; i<nlen-2; i++) { clone(node->neighbors[i]); } } void restore(UndirectedGraphNode *node) { if (node == NULL) { return; } int nlen = node->neighbors.size(); if (nlen < 2 || node->neighbors[nlen-2] != NULL) { return; } node->neighbors.pop_back(); node->neighbors.pop_back(); nlen-=2; for (int i=0; i<nlen; i++) { restore(node->neighbors[i]); } } };
/** * Definition for undirected graph. * struct UndirectedGraphNode { * int label; * vector<UndirectedGraphNode *> neighbors; * UndirectedGraphNode(int x) : label(x) {}; * }; */ // 10:15 class Solution { private: unordered_map<UndirectedGraphNode *, UndirectedGraphNode *> addr; public: UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) { if (node == NULL) { return NULL; } addr.clear(); return dfs(node); } UndirectedGraphNode * dfs(UndirectedGraphNode *node) { if (node == NULL) return NULL; if (addr.count(node) > 0) { return addr[node]; } UndirectedGraphNode* tmp = new UndirectedGraphNode(node->label); addr[node] = tmp; int len = node->neighbors.size(); for (int i=0; i<len; i++) { tmp->neighbors.push_back(node->neighbors[i]); } for (int i=0; i<len; i++) { tmp->neighbors[i] = dfs(tmp->neighbors[i]); } return tmp; } };