leetcode:133. 克隆图

题目来源

题目描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

class Node {
public:
    int val;
    vector<Node*> neighbors;
    Node() {
        val = 0;
        neighbors = vector<Node*>();
    }
    Node(int _val) {
        val = _val;
        neighbors = vector<Node*>();
    }
    Node(int _val, vector<Node*> _neighbors) {
        val = _val;
        neighbors = _neighbors;
    }
};



class Solution {
public:
    Node* cloneGraph(Node* node) {
        
    }
};

题目解析

这道题本质是要求遍历一个图,通常有两种方法

深度优先遍历

为了深拷贝出整张图,我们需要知道整张图的结构已经对应节点的值。

由于题目值给了我们一个节点的引用,因此为了知道整张图的结构已经对应节点的值,我们需要从给定的节点出发,进行图的遍历,并在遍历的过程中完成图的深拷贝

为了避免在深拷贝时陷入死循环,我们需要理解图的结构。对于一张无向图,任何给定的无向边都可以表示为两个有向边
在这里插入图片描述

为了防止多次遍历同一个节点,陷入死循环,我们需要一种数据结构记录已经被克隆过的节点

算法:

  • 使用一个哈希表存储所有已经被访问和克隆的节点。key是原始图中的节点,value是克隆对应节点
  • 从给定节点开始遍历图。如果某个节点已经被访问过,则返回其克隆图中的对应节点。
  • 如果当前访问的节点不在哈希表中,则创建它的克隆节点并存储在哈希表中。
  • 递归调用克隆每个节点的邻接点。

class Solution {
   std::unordered_map<Node*, Node *> visited;
public:
    
    Node* cloneGraph(Node* node) {
        if(node == nullptr){
            return nullptr;
        }
        
        if(visited[node] != nullptr){
            return visited[node];
        }
        
        Node* clone = new Node(node->val);
        visited[node] = clone;
        
        for(auto & neighbor : node->neighbors){
            clone->neighbors.emplace_back(cloneGraph(neighbor));
        }
        return clone;
    }
};

在这里插入图片描述

广度优先遍历

方法一与方法二的区别仅在于搜索的方式。深度优先搜索以深度优先,广度优先搜索以广度优先。这两种方法都需要借助哈希表记录被克隆过的节点来避免陷入死循环。

算法

  • 使用一个哈希表visited存储所有已经被访问和克隆的节点。哈希表中的key是原始图中的节点,value是克隆图中的节点
  • 将题目中给定的节点添加到队列。克隆该节点并存储到哈希表
  • 每次从队列首部取出一个节点,遍历该节点所有的邻接点。
    • 如果某个邻接点已经被访问,则该邻接点一定在visited中,那么从从 visited 获得该邻接点,否则创建一个新的节点存储在 visited 中,并将邻接点添加到队列。将克隆的邻接点添加到克隆图对应节点的邻接表中。
  • 重复上述操作直到队列为空,则整个图遍历结束。
class Solution {
   
public:
 
    Node* cloneGraph(Node* node) {
        if(node == nullptr){
            return nullptr;
        }

        std::unordered_map<Node*, Node *> visited;
        std::queue<Node *> queue;
        queue.push(node);
        visited[node] = new Node(node->val);
        while (!queue.empty()){
            auto orignal_node = queue.front(); queue.pop();
            auto clone_node = visited[orignal_node];
            for(auto neighbor : orignal_node->neighbors){
                auto cloneNeighbor = visited[neighbor];
                if(cloneNeighbor == nullptr){
                    cloneNeighbor = new Node(neighbor->val);
                    visited[neighbor] = cloneNeighbor;
                    queue.push(neighbor);
                }
                clone_node->neighbors.emplace_back(cloneNeighbor);
            }
        }
        return visited[node];
    }
};

类似题目

题目思路
leetcode:133. 克隆图 Clone Graph
leetcode:138. 复制带随机指针的链表 Copy List with Random Pointer
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值