LeetCode 力扣 133. 克隆圖

題目描述(中等難度)

復(fù)制一個圖,圖的節(jié)點定義如下。

class Node {
    public int val;
    public List<Node> neighbors;

    public Node() {}

    public Node(int _val,List<Node> _neighbors) {
        val = _val;
        neighbors = _neighbors;
    }
};

neighbors 是一個裝 Nodelist ,因為對象的話,java 變量都存儲的是引用,所以復(fù)制的話要新 new 一個 Node 放到 neighbors。

思路分析

這個題其實就是對圖進(jìn)行一個遍歷,通過 BFS 或者 DFS。需要解決的問題就是怎么添加當(dāng)前節(jié)點的 neighbors,因為遍歷當(dāng)前節(jié)點的時候,它的鄰居節(jié)點可能還沒有生成。

解法一 BFS

先來一個簡單粗暴的想法。

首先對圖進(jìn)行一個 BFS,把所有節(jié)點 new 出來,不處理 neighbors ,并且把所有的節(jié)點存到 map 中。

然后再對圖做一個 BFS,因為此時所有的節(jié)點已經(jīng)創(chuàng)建了,只需要更新所有節(jié)點的 neighbors。

public Node cloneGraph(Node node) {
    if (node == null) {
        return node;
    }
    //第一次 BFS
    Queue<Node> queue = new LinkedList<>();
    Map<Integer, Node> map = new HashMap<>();
    Set<Integer> visited = new HashSet<>();
    queue.offer(node);
    visited.add(node.val);
    while (!queue.isEmpty()) {
        Node cur = queue.poll();
        //生成每一個節(jié)點
        Node n = new Node();
        n.val = cur.val;
        n.neighbors = new ArrayList<Node>();
        map.put(n.val, n);
        for (Node temp : cur.neighbors) {
            if (visited.contains(temp.val)) {
                continue;
            }
            queue.offer(temp);
            visited.add(temp.val);
        }
    }

    //第二次 BFS 更新所有節(jié)點的 neightbors
    queue = new LinkedList<>();
    queue.offer(node);
    visited = new HashSet<>();
    visited.add(node.val);
    while (!queue.isEmpty()) {
        Node cur = queue.poll();
        for (Node temp : cur.neighbors) {
            map.get(cur.val).neighbors.add(map.get(temp.val));
        }
        for (Node temp : cur.neighbors) {
            if (visited.contains(temp.val)) {
                continue;
            }
            queue.offer(temp);
            visited.add(temp.val);
        }
    }
    return map.get(node.val);
}

當(dāng)然再仔細(xì)思考一下,其實我們不需要兩次 BFS。

我們要解決的問題是遍歷當(dāng)前節(jié)點的時候,鄰居節(jié)點沒有生成,那么我們可以一邊遍歷一邊生成鄰居節(jié)點,就可以同時更新 neighbors了。

同樣需要一個 map 記錄已經(jīng)生成的節(jié)點。

public Node cloneGraph(Node node) {
    if (node == null) {
        return node;
    }
    Queue<Node> queue = new LinkedList<>();
    Map<Integer, Node> map = new HashMap<>();
    queue.offer(node);
    //先生成第一個節(jié)點
    Node n = new Node();
    n.val = node.val;
    n.neighbors = new ArrayList<Node>();
    map.put(n.val, n);
    while (!queue.isEmpty()) {
        Node cur = queue.poll();
        for (Node temp : cur.neighbors) {
            //沒有生成的節(jié)點就生成
            if (!map.containsKey(temp.val)) {
                n = new Node();
                n.val = temp.val;
                n.neighbors = new ArrayList<Node>();
                map.put(n.val, n);
                queue.offer(temp);
            }
            map.get(cur.val).neighbors.add(map.get(temp.val));
        }
    }

    return map.get(node.val);
}

解法二 DFS

DFS 的話用遞歸即可,也用一個 map 記錄已經(jīng)生成的節(jié)點。

public Node cloneGraph(Node node) {
    if (node == null) {
        return node;
    }
    Map<Integer, Node> map = new HashMap<>();
    return cloneGrapthHelper(node, map);
}

private Node cloneGrapthHelper(Node node, Map<Integer, Node> map) {
    if (map.containsKey(node.val)) {
        return map.get(node.val);
    }
    //生成當(dāng)前節(jié)點
    Node n = new Node();
    n.val = node.val;
    n.neighbors = new ArrayList<Node>();
    map.put(node.val, n);
    //添加它的所有鄰居節(jié)點
    for (Node temp : node.neighbors) {
        n.neighbors.add(cloneGrapthHelper(temp, map));
    }
    return n;
}

這道題本質(zhì)上就是對圖的遍歷,只要想到用 map 去存儲已經(jīng)生成的節(jié)點,題目基本上就解決了。

更多詳細(xì)通俗題解詳見 leetcode.wang 。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容