1. 程式人生 > >Leetcode:133.克隆圖

Leetcode:133.克隆圖

克隆一張無向圖,圖中的每個節點包含一個 label (標籤)和一個 neighbors (鄰接點)列表 。

OJ的無向圖序列化:

節點被唯一標記。

我們用 # 作為每個節點的分隔符,用 , 作為節點標籤和鄰接點的分隔符。

例如,序列化無向圖 {0,1,2#1,2#2,2}

該圖總共有三個節點, 被兩個分隔符  # 分為三部分。 

  1. 第一個節點的標籤為 0,存在從節點 0 到節點 1 和節點 2
     的兩條邊。
  2. 第二個節點的標籤為 1,存在從節點 1 到節點 2 的一條邊。
  3. 第三個節點的標籤為 2,存在從節點 2 到節點 2 (本身) 的一條邊,從而形成自環。

我們將圖形視覺化如下:

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

解題思路:

廣度優先搜尋,對映(unordered_map)。圖的克隆,也就是建立一個新的圖,使得舊圖和新圖的結構一致,每個結點存在對映關係,並且對應結點的值相等,並且鄰居的值也對應相等。

  1. 建立對映關係,結點與結點的對映。unordered_map<UndirectedGraphNode*, UndirectedGraphNode*>mp;
  2. 設定廣度搜索需要的佇列,Q,Qc分別對應原圖佇列以及克隆圖佇列。
  3. 首先克隆圖的第一個結點,*clone=new UndirectedGraphNode(node->label)。建立這兩個結點的對映關係mp[node]=clone。
  4. 下一步將克隆node結點的鄰居。克隆鄰居時會遇到兩種情況原圖的鄰居不能對映到新圖,也就意味著,需要建立新的結點然後建立對映關係。或者能找到對映關係,說明這對結點之前訪問過。例如,上面訪問上圖的1時,鄰居0能找到對映,因為之前被訪問,而鄰居2結點不能找到對映。不論之間有沒有訪問都需要將鄰居加入
  5. 加入鄰居之後,如果這個結點剛剛才被建立,那麼將這對結點分別加入自己的佇列。之後將當前訪問的結點出隊。
  6. 直到佇列為空,說明圖克隆完畢,return clone。

C++程式碼
class Solution {
public:
    UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
        if (node == NULL) return NULL;
        queue<UndirectedGraphNode*> Q,Qc;
        UndirectedGraphNode *clone=new UndirectedGraphNode(node->label), *temp,*tempc;
        unordered_map<UndirectedGraphNode*, UndirectedGraphNode*>mp;//兩個圖的對映
        Q.push(node); Qc.push(clone);
        mp[node] = clone;
        UndirectedGraphNode *p;
        while (!Q.empty()) {
            temp = Q.front();
            tempc = Qc.front();
            int size = temp->neighbors.size();
            for (int i = 1; i <= size; i++) {
                p = temp->neighbors[i - 1];
                if (mp[p] == NULL) {
                    UndirectedGraphNode* newC = new UndirectedGraphNode(p->label);
                    tempc->neighbors.push_back(newC);
                    Q.push(p);
                    Qc.push(newC);
                    mp[p] = newC;
                }
                else {
                    tempc->neighbors.push_back(mp[p]);
                }
            }
            Q.pop();
            Qc.pop();
        }
        return clone;
    }
};