[LintCode/LeetCode] Clone Graph [BFS/DFS]

Problem

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

We use # as a separator for each node, and , as a separator for node label and each neighbor of the node.ide

return a deep copied graph.code

Example

How we serialize an undirected graph.
Nodes are labeled uniquely.
As an example, consider the serialized graph {0,1,2#1,2#2,2}.orm

The graph has a total of three nodes, and therefore contains three parts as separated by #.three

First node is labeled as 0. Connect node 0 to both nodes 1 and 2.
Second node is labeled as 1. Connect node 1 to node 2.
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:get

1
  / \
 /   \
0 --- 2
     / \
     \_/

Note

開始看這道題目的時候,沒有看懂queue和hashmap的做用。
複製一個無向圖,先分析圖的結構:label至關於圖結點的value,而neighbors至關於圖結點的全部next。而後考慮用什麼方式複製:用queue用來標記當前正在複製的或已經複製過的結點cur,而hashmap用來進行對新建無向圖結點root進行復制labelneighbors的操做。首先,從node結點開始,放入queue。而後對這個放入queue的結點cur開始操做:遍歷cur的全部neighbors,當前遍歷到的的neighbors叫作next。若map中不存在這個點,即沒有被複制過,就在map中複製這個結點nextlabel,同時存入queue以便在下次循環取出並複製其neighbors;不管map中包不包含這個neighbors結點next,都要將next加入map中對應新建結點rootneighbors。當BFS完成,則queue中沒有新的結點了,退出while循環。返回在map中更新過的root,結束。
map.get(cur).neighbors.add(map.get(next));
這一句能夠理解爲,在for循環對curneighbors的遍歷中,先在HashMap裏的root中創建新結點next,再將next放進root的結點curneighbors裏。hash

Solution

// Definition for undirected graph.
class UndirectedGraphNode {
    int label;ArrayList<UndirectedGraphNode> neighbors;
    UndirectedGraphNode(int x) { 
        label = x; 
        neighbors = new ArrayList<UndirectedGraphNode>(); 
    }
}
public class Solution {
    public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
        if (node == null) return null;
        UndirectedGraphNode root = new UndirectedGraphNode(node.label);//複製根節點
        Queue<UndirectedGraphNode> queue = new LinkedList<>();
        Map<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<>();
        queue.offer(node);//queue放入根結點
        map.put(node, root);//map放入根結點和它的複製結點
        while (!queue.isEmpty()) {
            UndirectedGraphNode cur = queue.poll();//取出queue中(同一層)的結點進行BFS
            for (UndirectedGraphNode n: cur.neighbors) {
                //對沒有複製過的結點進行復制,並將這個結點放入queue
                if (!map.containsKey(n)) {
                    map.put(n, new UndirectedGraphNode(n.label));
                    queue.offer(n);
                }
                //鏈接複製結點和複製neighbor結點
                map.get(cur).neighbors.add(map.get(n));
            }
        }
        return root;
    }
}

Update 2018-9 BFS

public class Solution {
    public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
        if (node == null) return node;

        Map<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<>();
        map.put(node, new UndirectedGraphNode(node.label));                     //<k, v>: <原結點, 複製結點>
        
        Queue<UndirectedGraphNode> queue = new LinkedList<>();
        queue.offer(node);                                                      //copy過的結點存入queue,以繼續遍歷其neighbor結點
        
        while (!queue.isEmpty()) {
            UndirectedGraphNode cur = queue.poll();                             //取出copy過的結點,繼續複製其全部neighbor結點
            for (UndirectedGraphNode neighbor: cur.neighbors) {
                if (!map.containsKey(neighbor)) {                               //若結點未複製過,copy後存入queue
                    map.put(neighbor, new UndirectedGraphNode(neighbor.label));
                    queue.offer(neighbor);
                }
                map.get(cur).neighbors.add(map.get(neighbor));                  //將每一個copied neighbor存入copied parent node
            }
        }
        return map.get(node);                                                   //返回copied根節點
    }
}

DFSit

public class Solution {
   public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
        Map<UndirectedGraphNode, UndirectedGraphNode> map = new HashMap<>();
        return cloneNode(node, map);
    }
    private UndirectedGraphNode cloneNode(UndirectedGraphNode node, Map<UndirectedGraphNode, UndirectedGraphNode> map) {
        if (node == null) return node;
        if (map.containsKey(node)) {
            return map.get(node);
        } else {
            UndirectedGraphNode nodeCopy = new UndirectedGraphNode(node.label);
            map.put(node, nodeCopy);
            for (UndirectedGraphNode child : node.neighbors) {
                nodeCopy.neighbors.add(cloneNode(child, map));
            }
            return nodeCopy;
        }
    }
}
相關文章
相關標籤/搜索