Clone Graph

描述

Clone an undirected graph. Each node in the graph contains a label and a list of its neighbours.

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 neighbour 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 node 0 to both nodes 1 and 2.
  • Second node is labeled as 1. Connect node 1 to node 2.
  • Third node is labeled as 2. Connect node 2 to node 2 (itself), thus forming a self-cycle.
    Visually, the graph looks like the following:
  1. 1
  2. / \
  3. / \
  4. 0 --- 2
  5. / \
  6. \_/

分析

广度优先遍历或深度优先遍历都可以。

DFS

  1. // Clone Graph
  2. // DFS,时间复杂度O(n),空间复杂度O(n)
  3. class Solution {
  4. public:
  5. UndirectedGraphNode *cloneGraph(const UndirectedGraphNode *node) {
  6. if(node == nullptr) return nullptr;
  7. // key is original node,value is copied node
  8. unordered_map<const UndirectedGraphNode *,
  9. UndirectedGraphNode *> visited;
  10. clone(node, visited);
  11. return visited[node];
  12. }
  13. private:
  14. // DFS
  15. static UndirectedGraphNode* clone(const UndirectedGraphNode *node,
  16. unordered_map<const UndirectedGraphNode *,
  17. UndirectedGraphNode *> &visited) {
  18. // a copy already exists
  19. if (visited.find(node) != visited.end()) return visited[node];
  20. UndirectedGraphNode *new_node = new UndirectedGraphNode(node->label);
  21. visited[node] = new_node;
  22. for (auto nbr : node->neighbors)
  23. new_node->neighbors.push_back(clone(nbr, visited));
  24. return new_node;
  25. }
  26. };

BFS

  1. // Clone Graph
  2. // BFS,时间复杂度O(n),空间复杂度O(n)
  3. class Solution {
  4. public:
  5. UndirectedGraphNode *cloneGraph(const UndirectedGraphNode *node) {
  6. if (node == nullptr) return nullptr;
  7. // key is original node,value is copied node
  8. unordered_map<const UndirectedGraphNode *,
  9. UndirectedGraphNode *> copied;
  10. // each node in queue is already copied itself
  11. // but neighbors are not copied yet
  12. queue<const UndirectedGraphNode *> q;
  13. q.push(node);
  14. copied[node] = new UndirectedGraphNode(node->label);
  15. while (!q.empty()) {
  16. const UndirectedGraphNode *cur = q.front();
  17. q.pop();
  18. for (auto nbr : cur->neighbors) {
  19. // a copy already exists
  20. if (copied.find(nbr) != copied.end()) {
  21. copied[cur]->neighbors.push_back(copied[nbr]);
  22. } else {
  23. UndirectedGraphNode *new_node =
  24. new UndirectedGraphNode(nbr->label);
  25. copied[nbr] = new_node;
  26. copied[cur]->neighbors.push_back(new_node);
  27. q.push(nbr);
  28. }
  29. }
  30. }
  31. return copied[node];
  32. }
  33. };

原文: https://soulmachine.gitbooks.io/algorithm-essentials/content/cpp/graph/clone-graph.html