【LeetCode】111. 二叉樹的最小深度(BFS 解題套路框架,要會默寫)

一、BFS 知識點

BFS 就是廣度優先 (Breadth first search)。與之對應的還有深度優先 (Depth first search)。

網上找到一篇文章,比較通俗易懂的介紹了這 2 者。

今天重點是 BFS ,用它解決比如找到從起點 start 到終點 target 的最近距離問題(黑色起點、紅色終點)。

BFS 相對 DFS 的最主要的區別是:BFS 找到的路徑一定是最短的,但代價就是空間複雜度可能比 DFS 大很多

BFS 的核心思想就是把一些問題抽象成圖,從一個點開始,向四周開始擴散

一般來說,我們寫 BFS 算法都是用隊列這種數據結構,每次將一個節點周圍的所有節點加入隊列。

這是框架,來自【labuladong】公衆號的學習資源。這裏要逐行閱讀理解,並記憶。

// 計算從起點 start 到終點 target 的最近距離
int BFS(Node start, Node target) {
    Queue<Node> q; // 核心數據結構
    Set<Node> visited; // 避免走回頭路
    
    q.offer(start); // 將起點加入隊列
    visited.add(start);
    int step = 0; // 記錄擴散的步數

    while (q not empty) {
        int sz = q.size();
        /* 將當前隊列中的所有節點向四周擴散 */
        for (int i = 0; i < sz; i++) {
            Node cur = q.poll();
            /* 劃重點:這裏判斷是否到達終點 */
            if (cur is target)
                return step;
            /* 將 cur 的相鄰節點加入隊列 */
            for (Node x : cur.adj())
                if (x not in visited) {
                    q.offer(x);
                    visited.add(x);
                }
        }
        /* 劃重點:更新步數在這裏 */
        step++;
    }
}

代碼裏的一些方法說明:

  • q.offer(start),往隊列尾部插入元素,當超出隊列界限的時候,返回 false 。
  • q.poll(),獲取並刪除Queue中的第一個元素。
  • visited.add(start),向 set 集合裏添加元素。
  • 隊列 q 是 BFS 的核心數據結構。
  • cur.adj()泛指 cur 相鄰的節點,比如說二維數組中,cur 上下左右四面的位置就是相鄰節點。
  • visited 的主要作用是防止走回頭路,大部分時候都是必須的。但是像一般的二叉樹結構,沒有子節點到父節點的指針,不會走回頭路就不需要 visited。

二、BFS 解決二叉樹的最小深度

給定一個二叉樹,找出其最小深度。

最小深度是從根節點到最近葉子節點的最短路徑上的節點數量。

說明:葉子節點是指沒有子節點的節點。

之前的做法:

class Solution {
    public int minDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        // 左右孩子都爲null,返回 1
        if (root.left == null && root.right == null) {
            return 1;
        }
        int leftHeight = minDepth(root.left);
        int rightHeight = minDepth(root.right);
        // 左右孩子有一個爲null
        if (leftHeight == 0 || rightHeight == 0) {
            return leftHeight + rightHeight + 1;
        }
        // 左右孩子都不爲null,返回比較最短的 + 1
        return Math.min(leftHeight, rightHeight) + 1;
    }
}

使用 BFS ,套用框架:

  • 起點就是根節點
  • 終點就是最靠近根節點的那個「葉子節點」
  • 葉子節點就是兩個子節點都是 null 的節點
class Solution {
    public int minDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root); // 將起點加入隊列
        int depth = 1; // root 本身就是一層,depth 初始化爲 1

        while (!q.isEmpty()) {
            // 將當前隊列中的所有節點向四周擴散
            int sz = q.size();
            for (int i = 0; i < sz; i++) {
                TreeNode cur = q.poll();  // 獲取並刪除Queue中的第一個元素
                /* 劃重點:這裏判斷是否到達終點 */
                if (cur.left == null && cur.right == null) {
                    return depth;
                }
                /* 將 cur 的相鄰節點加入隊列 */
                if (cur.left != null) {
                    q.offer(cur.left);
                }
                if (cur.right != null) {
                    q.offer(cur.right);
                }
            }
            /* 這裏增加步數 */
            depth++;
        }
        return depth;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章