zoukankan      html  css  js  c++  java
  • 【LeetCode】133. Clone Graph (3 solutions)

    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 = 0; 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 = 0; 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, 0);
            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], 0);
                                stk.push(topnei);
                            }
                            top->ind ++;
                            break;
                        }
                        else
                        {
                            topCopy->neighbors.push_back(m[top->node->neighbors[top->ind]]);
                            top->ind ++;
                        }
                    }
                }
            }
            return m[node];
        }
    };

  • 相关阅读:
    Cocos2d-x学习-郝盟主的《城市跑酷》分析学习 (一)GameSprite类
    PictureShare开发(二)地图Mark(标记)的处理(2)
    PictureShare开发(二)地图Mark(标记)的处理(1)
    Unity AssetBundle 踩坑记录
    Unity 配置静态excel 工作流程
    Spine U3D整合流程问题
    Destroy reall destroy ?!
    Drawing-Order-Of-meshes-and-sprites
    Split Animation Clip From FBX and Multiply Mode Sprite
    KBengine Learning Note 1 => Run Demo
  • 原文地址:https://www.cnblogs.com/ganganloveu/p/4119462.html
Copyright © 2011-2022 走看看