lone 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 / \ \_/
用一个map(unordered_map)保存原始node和新node的对应关系,一旦遍历到一个node发现对应的新node已经建立过,则直接找到并返回,否则建立新的节点,并copy neighbours。
两种遍历方法,BFS和DFS。
1. DFS。
class Solution {
public:
UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
if(node == NULL) return node;
//record the already copied nodes
unordered_map<UndirectedGraphNode*, UndirectedGraphNode*> copied;
dfs(node, copied);
return copied[node];
}
UndirectedGraphNode* dfs(UndirectedGraphNode *original, unordered_map<UndirectedGraphNode*, UndirectedGraphNode*> &copied)
{
if(copied.find(original) != copied.end())
return copied[original];
UndirectedGraphNode *newnode = new UndirectedGraphNode(original->label);
copied[original] = newnode;
for(auto neighbour : original->neighbors)
{
//here we cannot copy the original neighbour to the new adj list
//newnode->neighbors.push_back(neighbour);
UndirectedGraphNode* newneighbour = dfs(neighbour, copied);
newnode->neighbors.push_back(newneighbour);
}
return newnode;
}
};
2. BFS.
class Solution {
public:
UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
if(node == NULL) return node;
//record the already copied nodes
unordered_map<UndirectedGraphNode*, UndirectedGraphNode*> copied;
queue<UndirectedGraphNode*> Q;
UndirectedGraphNode* newcur = new UndirectedGraphNode(node->label);
copied[node] = newcur;
Q.push(node);
while(!Q.empty())
{
UndirectedGraphNode* cur = Q.front();
Q.pop();
for(auto neighbour : cur->neighbors)
{
UndirectedGraphNode* newneighbour;
if(copied.find(neighbour) != copied.end())
newneighbour = copied[neighbour];
else
{
newneighbour = new UndirectedGraphNode(neighbour->label);
copied[neighbour] = newneighbour;
Q.push(neighbour);
}
copied[cur]->neighbors.push_back(newneighbour);
}
}
return copied[node];
}
};
3. Non-recursive DFS.
http://blog.csdn.net/starmsg/article/details/39207445 很多细节需要注意。
class Solution {
public:
typedef vector<UndirectedGraphNode *>::iterator adj_iter;
UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node)
{
if(node == NULL) return NULL;
unordered_map<UndirectedGraphNode*, UndirectedGraphNode*> visited;
UndirectedGraphNode *newnode = dfs(node, visited);
return newnode;
}
UndirectedGraphNode *dfs(UndirectedGraphNode *node, unordered_map<UndirectedGraphNode*, UndirectedGraphNode*> &visited)
{
UndirectedGraphNode *newnode = new UndirectedGraphNode(node->label);
stack<pair<UndirectedGraphNode*,adj_iter>> stack;
stack.push(make_pair(node, node->neighbors.begin()));
visited[node] = newnode;
while(!stack.empty())
{
UndirectedGraphNode *cur = stack.top().first;
adj_iter iter = stack.top().second;
if(iter != cur->neighbors.end())
{
UndirectedGraphNode *next = *iter;
stack.top().second = ++iter; //be careful about how to change the iterator value
if(visited.find(next) == visited.end())
{
UndirectedGraphNode *newnext = new UndirectedGraphNode(next->label);
visited[next] = newnext;
visited[cur]->neighbors.push_back(newnext);
stack.push(make_pair(next, next->neighbors.begin()));
}
else
{
visited[cur]->neighbors.push_back(visited[next]);
}
}
else
stack.pop();
}
return newnode;
}
};