LeetCode || Clone Graph

Clone Graph

  Total Accepted: 11444  Total Submissions: 52034 My Submissions

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
         / \
         \_/

Have you been asked this question in an interview? 
      即克隆一个无向图,可能有环;乍一看没有思路,感觉可以用递归做,想一想,对于图的问题,有深度优先遍历DFS和广度优先遍历BFS,本题应该先进行BFS,目的是新建所有节点,并把节点存入map中,然后再次BFS遍历,为节点添加关系;也可以在一次BFS遍历中实现,但是要记住那些node已经被访问过,防止在环中出现死循环;代码如下:

/**
 * Definition for undirected graph.
 * struct UndirectedGraphNode {
 *     int label;
 *     vector<UndirectedGraphNode *> neighbors;
 *     UndirectedGraphNode(int x) : label(x) {};
 * };
 */
class Solution {
public:
    UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
        unordered_map<int, UndirectedGraphNode*> mp;
        unordered_map<UndirectedGraphNode*, int> visited;
        if(node==NULL)
            return NULL;
        UndirectedGraphNode *head = new UndirectedGraphNode(node->label);
        mp[node->label] = head;
        queue<UndirectedGraphNode*> que;
        que.push(node);
        while(!que.empty()){
            UndirectedGraphNode *p = que.front();
            que.pop();
            if(visited.find(p)==visited.end()){     //防止某个node指向自己,产生死循环
                for(int i=0; i<p->neighbors.size(); ++i){
                   que.push(p->neighbors[i]);
                   if(mp.find(p->neighbors[i]->label)==mp.end()){
                        UndirectedGraphNode *temp = new UndirectedGraphNode(p->neighbors[i]->label);
                        mp[p->neighbors[i]->label] = temp;
                    }
                    mp[p->label]->neighbors.push_back(mp[p->neighbors[i]->label]);
                }
                visited[p] = 1;
            }
            
        }
        return head;
    }
};

      一直在想,能不能不用记录node是否被访问的状态,而实现一次遍历完成复制,网上看到一网友的代码,用map中是否存在来代替访问状态,即如果此node已经被新建了,那么说明他已经被访问,另外,在遍历某个node的neighbors时,要给是否将该邻居加入queue加上条件,那就是如果该点已经存在,就说明该点要么已经被访问过,要么就已经在queue中了,所以不再加入queue,代码如下:

/**
 * Definition for undirected graph.
 * struct UndirectedGraphNode {
 *     int label;
 *     vector<UndirectedGraphNode *> neighbors;
 *     UndirectedGraphNode(int x) : label(x) {};
 * };
 */
class Solution {
public:
    UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
        unordered_map<int, UndirectedGraphNode*> mp;
        if(node==NULL)
            return NULL;
        queue<UndirectedGraphNode*> que;
        que.push(node);
        while(!que.empty()){
            UndirectedGraphNode *p = que.front();
            que.pop();
            if(mp.find(p->label)==mp.end()){
                UndirectedGraphNode *temp = new UndirectedGraphNode(p->label);
                mp[p->label] = temp;
            }
            for(int i=0; i<p->neighbors.size(); ++i){
               if(mp.find(p->neighbors[i]->label)==mp.end()){
                    UndirectedGraphNode *temp = new UndirectedGraphNode(p->neighbors[i]->label);
                    mp[p->neighbors[i]->label] = temp;
                    que.push(p->neighbors[i]);      //如果node已经存在,那么就不再加入queue中,这样实现避免死循环
                }
                mp[p->label]->neighbors.push_back(mp[p->neighbors[i]->label]);  //环关系的建立在这里
            }

        }
        return mp[node->label];
    }
};

总结:时间复杂度O(N),空间复杂度O(N)。

要注重map的使用,灵活运用map存储指针。









你可能感兴趣的:(LeetCode)