28 克隆图(Clone Graph)

1 题目

题目:克隆图(Clone Graph)
描述:克隆一张无向图。无向图的每个节点包含一个 label 和一个列表 neighbors。保证每个节点的 label 互不相同。程序需要返回一个经过深度拷贝的新图。新图和原图具有同样的结构, 并且对新图的任何改动不会对原图造成任何影响。

lintcode题号——137,难度——medium

样例1:

输入:
{1,2,4#2,1,4#4,1,2}
输出: 
{1,2,4#2,1,4#4,1,2}
解释:
1------2  
 \     |  
  \    |  
   \   |  
    \  |  
      4   

关于图的序列化规则:

{1,2,4#2,1,4#3,5#4,1,2#5,3} 序列表示的图如下
1------2  3
 \     |  | 
  \    |  |
   \   |  |
    \  |  |
      4   5
序列中使用 # 分隔节点信息。
1,2,4 表示 2和4 是1的相邻节点;
2,1,4 表示 1和4 是2的相邻节点;
3,5 表示 5 是3的相邻节点;
4,1,2 表示 1和2 是4的相邻节点;
5,3 表示 3 是5的相邻节点。

2 解决方案

2.1 思路

  题意是对一个无向图进行深度拷贝,可以考虑先拷贝节点,再新旧节点之间进行映射,使我们能够通过旧节点找到新节点,再拷贝边,即将旧节点的邻居所映射的新节点,作为新邻居赋给该旧节点所映射的新节点。

需要注意的是,很容易将旧邻居直接赋给新节点,这样是错误的,因为旧节点对应的邻居也是旧的,需要各自找到映射的新邻居。

2.2 时间复杂度

  图上的宽度优先搜索,算法的时间复杂度为O(n+m),其中n为节点数,m为边数。

因为在图中的m的数量级最高是n的平方,所以也可以认为是O(m)。

2.3 空间复杂度

  图上的宽度优先搜索,使用了queue队列数据结构保存节点,算法的空间复杂度为O(n)。

3 源码

细节:

  1. 使用宽度优先搜索获取所有点;
  2. 克隆所有点,并映射新旧节点,需要从旧节点向新节点映射;
  3. 旧点->旧邻居们->新邻居们,连接新点与新邻居们。

C++版本:

/**
 * Definition for undirected graph.
 * struct UndirectedGraphNode {
 *     int label;
 *     vector<UndirectedGraphNode *> neighbors;
 *     UndirectedGraphNode(int x) : label(x) {};
 * };
 */
/**
 * @param node: A undirected graph node
 * @return: A undirected graph node
 */
UndirectedGraphNode* cloneGraph(UndirectedGraphNode* node) {
    // write your code here
    if (node == NULL)
    {
        return NULL;
    }
    
    // 获取所有点
    set<UndirectedGraphNode *> setOldNodes = traverseNode(node);
    
    // 克隆节点,建立旧节点到新节点的映射
    map<UndirectedGraphNode *, UndirectedGraphNode *> mapNodes;
    for (auto n : setOldNodes)
    {
        mapNodes.insert(make_pair(n, new UndirectedGraphNode(n->label)));
    }
    
    // 克隆边
    for (auto n : setOldNodes)
    {
        for (auto neighbor : n->neighbors)
        {
            mapNodes.at(n)->neighbors.push_back(mapNodes.at(neighbor));
        }
    }
    
    return mapNodes.at(node);
}

set<UndirectedGraphNode *> traverseNode(UndirectedGraphNode * root)
{
    queue<UndirectedGraphNode *> nodeQueue;
    set<UndirectedGraphNode *> nodeSet;
    nodeQueue.push(root);
    nodeSet.insert(root);
    while (!nodeQueue.empty())
    {
        UndirectedGraphNode * cur = nodeQueue.front();
        nodeQueue.pop();
        for (auto n : cur->neighbors)
        {
            if (nodeSet.find(n) != nodeSet.end())
            {
                continue;
            }
            
            nodeSet.insert(n);
            nodeQueue.push(n);
        }
    }
    
    return nodeSet;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值