Clone Graph

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 #.

  1. First node is labeled as 0. Connect node 0 to both nodes 1 and 2.
  2. Second node is labeled as 1. Connect node 1 to node 2.
  3. 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
/ \
/ \
0 --- 2
/ \
\_/

这题只需一边遍历一遍复制就可以了。

因此至少可以用三种方法:

1、广度优先遍历(BFS)

2、深度优先遍历(DFS)

2.1、递归

2.2、非递归

解法一:广度优先遍历

变量说明:

映射表m用来保存原图结点与克隆结点的对应关系。

映射表visited用来记录已经访问过的原图结点,防止循环访问。

队列q用于记录广度优先遍历的层次信息。

/**
* Definition for undirected graph.
* struct UndirectedGraphNode {
* int label;
* vector<UndirectedGraphNode *> neighbors;
* UndirectedGraphNode(int x) : label(x) {};
* };
*/
class Solution {
public:
UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
if(node == NULL)
return NULL;
// map from origin node to copy node
unordered_map<UndirectedGraphNode *, UndirectedGraphNode *> m;
unordered_map<UndirectedGraphNode *, bool> visited;
queue<UndirectedGraphNode*> q;
q.push(node);
while(!q.empty())
{// BFS
UndirectedGraphNode* front = q.front();
q.pop(); if(visited[front] == false)
{
visited[front] = true; UndirectedGraphNode* cur;
if(m.find(front) == m.end())
{
cur = new UndirectedGraphNode(front->label);
m[front] = cur;
}
else
{
cur = m[front];
}
for(int i = ; i < front->neighbors.size(); i ++)
{
if(m.find(front->neighbors[i]) == m.end())
{
UndirectedGraphNode* nei = new UndirectedGraphNode(front->neighbors[i]->label);
m[front->neighbors[i]] = nei;
cur->neighbors.push_back(nei); q.push(front->neighbors[i]);
}
else
{
cur->neighbors.push_back(m[front->neighbors[i]]);
}
}
}
}
return m[node];
}
};

解法二:递归深度优先遍历(DFS)

/**
* Definition for undirected graph.
* struct UndirectedGraphNode {
* int label;
* vector<UndirectedGraphNode *> neighbors;
* UndirectedGraphNode(int x) : label(x) {};
* };
*/
class Solution {
public:
map<UndirectedGraphNode *, UndirectedGraphNode *> m; UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node)
{
if(node == NULL)
return NULL; if(m.find(node) != m.end()) //if node is visited, just return the recorded nodeClone
return m[node]; UndirectedGraphNode *nodeClone = new UndirectedGraphNode(node->label);
m[node] = nodeClone;
for(int st = ; st < node->neighbors.size(); st ++)
{
UndirectedGraphNode *temp = cloneGraph(node->neighbors[st]);
if(temp != NULL)
nodeClone->neighbors.push_back(temp);
}
return nodeClone;
}
};

解法三:非递归深度优先遍历(DFS)

深度优先遍历需要进行邻居计数。如果邻居已经全部访问,则该节点访问完成,可以出栈,否则就要继续处理下一个邻居。

/**
* Definition for undirected graph.
* struct UndirectedGraphNode {
* int label;
* vector<UndirectedGraphNode *> neighbors;
* UndirectedGraphNode(int x) : label(x) {};
* };
*/ struct Node
{
UndirectedGraphNode *node;
int ind; //next neighbor to visit
Node(UndirectedGraphNode *n, int i): node(n), ind(i) {}
}; class Solution {
public:
UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
if(node == NULL)
return NULL;
// map from origin node to copy node
unordered_map<UndirectedGraphNode *, UndirectedGraphNode *> m;
unordered_map<UndirectedGraphNode *, bool> visited;
stack<Node*> stk;
Node* newnode = new Node(node, );
stk.push(newnode);
visited[newnode->node] = true;
while(!stk.empty())
{// DFS
Node* top = stk.top();
UndirectedGraphNode* topCopy;
if(m.find(top->node) == m.end())
{
topCopy = new UndirectedGraphNode(top->node->label);
m[top->node] = topCopy;
}
else
topCopy = m[top->node]; if(top->ind == top->node->neighbors.size())
//finished copying its neighbors
stk.pop();
else
{
while(top->ind < top->node->neighbors.size())
{
if(m.find(top->node->neighbors[top->ind]) == m.end())
{
UndirectedGraphNode* neiCopy = new UndirectedGraphNode(top->node->neighbors[top->ind]->label);
m[top->node->neighbors[top->ind]] = neiCopy;
topCopy->neighbors.push_back(neiCopy);
if(visited[top->node->neighbors[top->ind]] == false)
{
visited[top->node->neighbors[top->ind]] = true;
Node* topnei = new Node(top->node->neighbors[top->ind], );
stk.push(topnei);
}
top->ind ++;
break;
}
else
{
topCopy->neighbors.push_back(m[top->node->neighbors[top->ind]]);
top->ind ++;
}
}
}
}
return m[node];
}
};

【LeetCode】133. Clone Graph (3 solutions)的更多相关文章

  1. 【LeetCode】133. Clone Graph 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 DFS BFS 日期 题目地址:https://le ...

  2. 【leetcode】133. Clone Graph

    题目如下: Given the head of a graph, return a deep copy (clone) of the graph. Each node in the graph con ...

  3. 【LeetCode】785. Is Graph Bipartite? 解题报告(Python)

    [LeetCode]785. Is Graph Bipartite? 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu. ...

  4. 133. Clone Graph (3 solutions)——无向无环图复制

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

  5. 【LeetCode】75. Sort Colors (3 solutions)

    Sort Colors Given an array with n objects colored red, white or blue, sort them so that objects of t ...

  6. 【LeetCode】90. Subsets II (2 solutions)

    Subsets II Given a collection of integers that might contain duplicates, S, return all possible subs ...

  7. 【Lintcode】137.Clone Graph

    题目: Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. ...

  8. 【LeetCode】207. Course Schedule (2 solutions)

    Course Schedule There are a total of n courses you have to take, labeled from 0 to n - 1. Some cours ...

  9. 【LeetCode】44. Wildcard Matching (2 solutions)

    Wildcard Matching Implement wildcard pattern matching with support for '?' and '*'. '?' Matches any ...

随机推荐

  1. 运行时类型识别RTTI

    1.RTTI的工作原理 例1. 用Class加载对象示例. package RTTI; public class Candy { static{ System.out.println("Lo ...

  2. CURL库在C++程序中的运用浅析

    最近由于要做一个爬虫项目,要对很多网站进行爬取,所以一直都在看这方面的文章.在翻阅了很多资料后,下载了一个curl库,着实对项目有了很大的帮助. 一.LibCurl基本编程框架 二.一些基本的函数 三 ...

  3. go语言基础之结构体成员的使用普通变量

    1.结构体成员的使用普通变量 示例: package main //必须有个main包 import "fmt" //定义一个结构体类型 type Student struct { ...

  4. maven 将jar 下载到工程当前目录下

    在 pom.xml 的目录下,运行cmd命令 : call mvn -f pom.xml dependency:copy-dependencies 然后在同一目录下出现文件夹target,内容就是ja ...

  5. Mac下开启与关闭端口转发的脚本配置方法

    一.依次运行以下命令: cd /etc ls | grep pf.conf sudo cp pf.conf pf.conf.normal.bak sudo cp pf.conf pf.conf.tra ...

  6. telnet 退出命令

    telnet xxx port ctrl + ] telnet > quit ctrl + w 是清除命令 转自: http://wangyifeng.blog.51cto.com/214490 ...

  7. XML基础以及用DOM4j读取数据

    都知道,HTML被设计用来显示数据,XML被设计用来保存.数据传输.而我们平时经经常使用的无非是保存数据.读取数据.所以这里主要介绍XML相关基础内容.以及用DOM4j来存取XML的数据. 以下简单介 ...

  8. B. Ohana Cleans Up(Codeforces Round #309 (Div. 2))

    B. Ohana Cleans Up   Ohana Matsumae is trying to clean a room, which is divided up into an n by n gr ...

  9. ZOJ 3587 扩展KMP

    思路:这题确实大帝做得非常机智!字符串先求最长前缀,反的字符串再求一次最长前缀.然后就能够搞了. 每一个子串出现的次数就是最长前缀的次数嘛! #pragma comment(linker, " ...

  10. redis可视化管理工具Redis Desktop Manager

    Redis Desktop Manager 官方下载地址:https://redisdesktop.com/download