iT邦幫忙

2024 iThome 鐵人賽

DAY 6
0
自我挑戰組

用 C/C++ 或 Rust 刷 Leetcode系列 第 6

「用BFS 一層層走」: 102. Binary Tree Level Order Traversal 與 1161. Maximum Level Sum of a Binary Tree

  • 分享至 

  • xImage
  •  

接續幾天會討論 Tree, Graph, DAG 與 topological。
今天討論的主題用 DFS/BFS 是 Tree,而 Tree 就是沒有 Cycle 的 Graph。

102. Binary Tree Level Order Traversal (medium)

題目敘述: 給一個二元樹的根節點,傳回其節點值的層序遍歷。

輸入輸出範例:

	   3
	 /  \
    9      20
          /  \
         15   7
Input: root = [3,9,20,null,null,15,7]
Output: [[3],[9,20],[15,7]]

我解題想法1 :用遞迴 DFS 方式寫的,在參數裡存好層數。

用 DFS 看輸入輸出範例 順序將會是:

3 -左-> 9 -左-> NULL
        -右-> NULL (返回到3)
  -右-> 20 -左-> 15
         -右-> 7  (結束)

(3, 9, 20, 15, 7)

獻上程式碼:

class Solution {
public:
    vector<vector<int>> res;
    void dfs(TreeNode * root, int level) {
        if (!root) return;
        if(res.size() < level+1) {
            res.push_back({root->val});
        }else{
            res[level].push_back(root->val);
        }
        dfs(root->left, level+1);
        dfs(root->right, level+1);
    }
    vector<vector<int>> levelOrder(TreeNode* root) {
        dfs(root, 0);
        return res;
    }
};

想法2 : 迭代的 BFS 走訪 Tree
題目的範例:

	   3
	 /  \
    9      20
          /  \
         15   7

BFS 走訪順序 3, 9, 20, 15, 7

我解題想法是將走訪最終結果想成是 [3, 9, 20, 15, 7] 一維結果。在 while 迴圈內的每次迭代都是走訪一個節點(非整層),因此我需要用三個整數去記錄走訪 Tree 的狀態: levelPtr (這層最後節點的位數), nextLevelPtr (下層最後節點的位數), currPtr (已遍歷的節點數量), (currPtr <= levelPtr <= nextLevelPtr) ,當遍歷完一層時 (if (levelPtr == currPtr)),將該層的節點們存入 res

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        if (!root) return {};
        vector<vector<int>> res;
        queue<TreeNode *> qu;
        qu.push(root);
        int levelPtr = 1, nextLevelPtr = 1, currPtr = 0;
        vector<int> tmp;

        while (!qu.empty()) {
            currPtr += 1;
            TreeNode* node = qu.front();
            qu.pop();
            tmp.push_back(node->val);
            if (node->left) {
                nextLevelPtr++;
                qu.push(node->left);
            }
            if (node->right) {
                nextLevelPtr++;
                qu.push(node->right);
            }
            if (levelPtr == currPtr) {
                res.push_back(tmp);
                tmp.clear();
                levelPtr = nextLevelPtr;
            }
        }
        return res;
    }
};

此題檢討:
看了 討論區的解答教授的解法 (兩者類似),發現 while 內的每次迭代是將該層的節點存進一個 vector 後,先記錄當層的節點數 (int s = qu.size();) ,此層的所有節點會被加入到一個臨時 vector 中。這樣的寫法讓整個程式碼變得更加簡潔

時間複雜度 O(n),走訪整棵 BFS tree。

1161. Maximum Level Sum of a Binary Tree (medium)

講解題目: 為每層的節點值算總和,返回最大總和的層數 (1-index)
102. Binary Tree Level Order Traversal 題目很像,以下程式碼是根據之前 BFS 的檢討寫出來的結果。

class Solution {
public:
    int maxLevelSum(TreeNode* root) {
        int maxLevel , currLevel = 0, maxSum = INT_MIN;
        queue<TreeNode *> qu;
        qu.push(root);
        while (!qu.empty()) {
            int quSize = qu.size(), currSum = 0;
            currLevel += 1;
            for (int i = 0; i < quSize; i++) {
                TreeNode *node = qu.front();
                currSum += node->val;
                qu.pop();
                if(node->left) qu.push(node->left);
                if(node->right) qu.push(node->right);
            }
            if (maxSum < currSum) {
                maxSum = currSum;
                maxLevel = currLevel;
            }
        }
        return maxLevel;
    }
};

時間複雜度同樣 O(n)

以上是我的解題紀錄,由於我的太生疏了,因此寫出來的程式碼還有很多的進步空間!

這幾天發現,將自己與他人的程式碼進行對比分析,能夠幫助我更加清晰地理解解題思路,這種自言自語式的分析就像是「黃色小鴨除錯法」啊!


上一篇
「撒麵包屑般的紀錄走過路徑」: 200. Number of Islands
下一篇
「直徑」: 543. Diameter of Binary Tree 與「塗色問題」: 785. Is Graph Bipartite?
系列文
用 C/C++ 或 Rust 刷 Leetcode30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言