Bootstrap

代码随想录算法训练营Day13 | LeetCode 二叉树的遍历 144 | 145 | 94 | 102 | 107 | 199 | 637 | 429 | 515 | 116|

今日任务

144. 二叉树的前序遍历

  • 题目链接: https://leetcode.cn/problems/binary-tree-preorder-traversal/description/
  • 题目描述
    给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

Code

递归
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ans;
        function<void(TreeNode *)> preOrder = [&] (TreeNode *node) -> void {
            if(node == nullptr){
                return;
            }
            ans.emplace_back(node->val);
            preOrder(node->left);
            preOrder(node->right);
        };
        preOrder(root);
        return ans;
    }
};
迭代 stack
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        // 迭代
        vector<int> ans;
        stack<TreeNode *> st;
        if(root == nullptr){
            return ans;
        }
        st.emplace(root);
        while(!st.empty()){
            TreeNode *cur = st.top();
            ans.emplace_back(cur->val);
            st.pop();
            if(cur->right){
                st.emplace(cur->right);
            }
            if(cur->left){
                st.emplace(cur->left);
            }
        }
        return ans;
    }
};

145. 二叉树的后序遍历

  • 题目链接: https://leetcode.cn/problems/binary-tree-postorder-traversal/description/
  • 题目描述
    给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。

Code

递归
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> ans;
        function<void(TreeNode *)> postOrder = [&] (TreeNode *node) -> void{
            if(node == nullptr){
                return;
            }
            postOrder(node->left);
            postOrder(node->right);
            ans.emplace_back(node->val);
        };
        postOrder(root);
        return ans;
    }
};
迭代
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        // 迭代
        vector<int> ans;
        stack<TreeNode *> st;
        if(root == nullptr){
            return ans;
        }
        st.emplace(root);
        while(!st.empty()){
            TreeNode *cur = st.top();
            st.pop();
            ans.emplace_back(cur->val);
            if(cur->left){
                st.emplace(cur->left);
            }
            if(cur->right){
                st.emplace(cur->right);
            }
        }
        reverse(ans.begin(), ans.end());
        return ans;
    }
};

94. 二叉树的中序遍历

  • 题目链接: https://leetcode.cn/problems/binary-tree-inorder-traversal/description/
  • 题目描述
    给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。

Code

递归
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ans;
        function<void(TreeNode *)> inOrder = [&] (TreeNode *node) -> void{
            if(node == nullptr){
                return;
            }
            inOrder(node->left);
            ans.emplace_back(node->val);
            inOrder(node->right);
        };
        inOrder(root);
        return ans;
    }
};
迭代
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        //迭代
        vector<int> ans;
        stack<TreeNode *> st;
        if(root == nullptr){
            return ans;
        }
        TreeNode *cur = root;
        while(cur || !st.empty()){
            if(cur){
                st.emplace(cur);
                cur = cur->left;
            }else{
                cur = st.top();
                st.pop();
                ans.emplace_back(cur->val);
                cur = cur->right;
            }
        }
        return ans;
        // 莫里斯遍历 将树变成链表
        // 如中序遍历,将根节点放在左子树的最右节点下
    }
};
标记

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        // White or Black
        enum Color{
            WHITE,
            BLACK
        };
        vector<int> ans;
        stack<pair<int, TreeNode *>> st;
        st.emplace(make_pair(WHITE, root));
        while(!st.empty()){
            auto [color, cur] = st.top();
            st.pop();
            if(cur == nullptr){
                continue;
            }
            if(color == WHITE){
                st.emplace(WHITE, cur->right);
                st.emplace(BLACK, cur);
                st.emplace(WHITE, cur->left);
            }else{
                ans.emplace_back(cur->val);
            }
        }
        return ans;
    }
};

统一风格遍历(魔功大成)

标记法,将标记和节点一起入栈

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        // White or Black
        enum Color{
            WHITE,
            BLACK
        };
        vector<int> ans;
        stack<pair<int, TreeNode *>> st;
        st.emplace(make_pair(WHITE, root));
        while(!st.empty()){
            auto [color, cur] = st.top();
            st.pop();
            if(cur == nullptr){
                continue;
            }
            if(color == WHITE){
                st.emplace(WHITE, cur->right);
                st.emplace(BLACK, cur);
                st.emplace(WHITE, cur->left);
            }else{
                ans.emplace_back(cur->val);
            }
        }
        return ans;
    }
};

添加nullptr,在应该输出的节点前加上空节点

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ans;
        stack<TreeNode *> st;
        if(root){
            st.emplace(root);
        }
        while(!st.empty()){
            TreeNode *cur = st.top();
            st.pop();
            if(cur){
                if(cur->right){
                    st.emplace(cur->right);
                }
                st.emplace(cur);
                st.emplace(nullptr);
                if(cur->left){
                    st.emplace(cur->left);
                }
            }else{
                ans.emplace_back(st.top()->val);
                st.pop();
            }
        }
        return ans;
    }
};

层序遍历

102. 二叉树的层序遍历

  • 题目链接: https://leetcode.cn/problems/binary-tree-level-order-traversal/description/
  • 题目描述
    给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

Code 队列 Or 双数组

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        // if(root == nullptr){
        //     return {};
        // }
        // vector<vector<int>> ans;
        // queue<TreeNode *> que;
        // que.emplace(root);
        // while(!que.empty()){
        //     int n = que.size();
        //     ans.emplace_back(vector<int>());
        //     for(int i = 0; i < n; i++){
        //         TreeNode *cur = que.front();
        //         que.pop();
        //         ans.back().emplace_back(cur->val);
        //         if(cur->left){
        //             que.emplace(cur->left);
        //         }
        //         if(cur->right){
        //             que.emplace(cur->right);
        //         }
        //     }
        // }
        // return ans;

        // double array
        if(root == nullptr){
            return {};
        }
        vector<vector<int>> ans;
        vector<TreeNode *> cur = {root}; // 直接赋值
        while(!cur.empty()){
            ans.emplace_back(vector<int>());
            vector<TreeNode *> next;
            for(auto & node : cur){
                ans.back().emplace_back(node->val);
                if(node->left){
                    next.emplace_back(node->left);
                }
                if(node->right){
                    next.emplace_back(node->right);
                }
            }
            cur = move(next); // 移动赋值
        }
        return ans;
    }
};

107. 二叉树的层序遍历 II

  • 题目链接: https://leetcode.cn/problems/binary-tree-level-order-traversal-ii/description/
  • 题目描述
    给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

Code 队列 Or 双数组

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        if(root == nullptr){
            return {};
        }
        vector<vector<int>> ans;
        // vector<TreeNode *> cur = {root};
        // while(!cur.empty()){
        //     ans.emplace_back(vector<int>());
        //     vector<TreeNode *> next;
        //     for(auto node : cur){
        //         ans.back().emplace_back(node->val);
        //         if(node->left){
        //             next.emplace_back(node->left);
        //         }
        //         if(node->right){
        //             next.emplace_back(node->right);
        //         }
        //     }
        //     cur = move(next);
        // }
        queue<TreeNode *> que;
        que.emplace(root);
        while(!que.empty()){
            int n = que.size();
            ans.emplace_back(vector<int>());
            for(int i = 0; i < n; i++){
                TreeNode *cur = que.front();
                que.pop();
                ans.back().emplace_back(cur->val);
                if(cur->left){
                    que.emplace(cur->left);
                }
                if(cur->right){
                    que.emplace(cur->right);
                }
            }
        }
        reverse(ans.begin(), ans.end());
        return ans;
    }
};

199. 二叉树的右视图

  • 题目链接: https://leetcode.cn/problems/binary-tree-right-side-view/description/
  • 题目描述
    给定一个二叉树的 根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
    在这里插入图片描述

Code 队列 Or 双数组 Or 递归

class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        // if(root == nullptr){
        //     return {};
        // }
        // vector<int> ans;

        // queue<TreeNode *> que;
        // que.emplace(root);
        // while(!que.empty()){
        //     int n = que.size();
        //     while(n--){
        //         auto cur = que.front();
        //         que.pop();
        //         if(n == 0){
        //             ans.emplace_back(cur->val);
        //         }
        //         if(cur->left){
        //             que.emplace(cur->left);
        //         }
        //         if(cur->right){
        //             que.emplace(cur->right);
        //         }
        //     }
        // }
        // vector<TreeNode *> cur = {root};
        // while(!cur.empty()){
        //     ans.emplace_back(cur.back()->val);
        //     vector<TreeNode *> next;
        //     for(auto node : cur){
        //         if(node->left){
        //             next.emplace_back(node->left);
        //         }
        //         if(node->right){
        //             next.emplace_back(node->right);
        //         }
        //     }
        //     cur = move(next);
        // }
        // return ans;

        vector<int> ans;
        function<void(TreeNode *, int)> dfs = [&] (TreeNode *node, int depth) -> void{
            if(node == nullptr){
                return;
            }
            if(depth == ans.size()){
                ans.emplace_back(node->val);
            }
            dfs(node->right, depth + 1);
            dfs(node->left, depth + 1);
        };
        dfs(root, 0);
        return ans;
    }
};

637. 二叉树的层平均值

  • 题目链接:https://leetcode.cn/problems/average-of-levels-in-binary-tree/description/
  • 题目描述
    给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值。与实际答案相差 10-5 以内的答案可以被接受。
    在这里插入图片描述

Code 队列 Or 双数组

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
        if(root == nullptr){
            return {};
        } 
        vector<double> ans;
        // queue<TreeNode *> que;
        // que.emplace(root);
        // while(!que.empty()){
        //     int n = que.size();
        //     double tmp = 0;
        //     for(int i = 0; i < n; i++){
        //         auto cur = que.front();
        //         que.pop();
        //         tmp += cur->val;
        //         if(cur->left){
        //             que.emplace(cur->left);
        //         }
        //         if(cur->right){
        //             que.emplace(cur->right);
        //         }
        //     }
        //     ans.emplace_back(tmp / n);
        // }

        vector<TreeNode *> cur = {root};
        while(!cur.empty()){
            double sum = 0;
            vector<TreeNode *> next;
            for(auto node : cur){
                sum += node->val;
                if(node->left){
                    next.emplace_back(node->left);
                }
                if(node->right){
                    next.emplace_back(node->right);
                }
            }
            ans.emplace_back(sum / cur.size());
            cur = move(next);
        }
        return ans;
    }
};

429. N 叉树的层序遍历

  • 题目链接: https://leetcode.cn/problems/n-ary-tree-level-order-traversal/description/
  • 题目描述

给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。

树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。
在这里插入图片描述

Code 队列 or 双数组

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        if(root == nullptr){
            return {};
        }
        vector<vector<int>> ans;
        // queue<Node *> que;
        // que.emplace(root);
        // while(!que.empty()){
        //     int n = que.size();
        //     ans.emplace_back(vector<int>());
        //     for(int i = 0; i < n; i++){
        //         auto cur = que.front();
        //         que.pop();
        //         ans.back().emplace_back(cur->val);
        //         for(auto node : cur->children){
        //             que.emplace(node);
        //         }
        //     }
        // }

        vector<Node *> cur = {root};
        while(!cur.empty()){
            ans.emplace_back(vector<int>());
            vector<Node *> next;
            for(auto &node : cur){
                ans.back().emplace_back(node->val);
                for (const auto& child : node->children) {
                    next.emplace_back(child);
                }
            }
            cur = move(next);
        }
        return ans;
    }
};

515. 在每个树行中找最大值

  • 题目链接:https://leetcode.cn/problems/find-largest-value-in-each-tree-row/description/
  • 题目描述
    给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。

Code 队列 or 双数组

class Solution {
public:
    vector<int> largestValues(TreeNode* root) {
        if(!root){
            return {};
        }
        vector<int> ans;
        // queue<TreeNode *> que;
        // que.emplace(root);
        // while(!que.empty()){
        //     int n = que.size();
        //     int target = INT_MIN;
        //     for(int i = 0; i < n; i++){
        //         auto cur = que.front();
        //         que.pop();
        //         target = max(target, cur->val);
        //         if(cur->left){
        //             que.emplace(cur->left);
        //         }
        //         if(cur->right){
        //             que.emplace(cur->right);
        //         }
        //     }
        //     ans.emplace_back(target);
        // }

        vector<TreeNode *> cur = {root};
        while(!cur.empty()){
            int target = INT_MIN;
            vector<TreeNode *> next;
            for(auto & node : cur){
                target = max(target, node->val);
                if(node->left){
                    next.emplace_back(node->left);
                }
                if(node->right){
                    next.emplace_back(node->right);
                }
            }
            cur = move(next);
            ans.emplace_back(target);
        }
        return ans;
    }
};

116. 填充每个节点的下一个右侧节点指针 && 117 相同

  • 题目链接: https://leetcode.cn/problems/populating-next-right-pointers-in-each-node/description/
  • 题目描述
    给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
    在这里插入图片描述

Code BFS + 队列 / 数组 or DFS递归 or BFS + List

class Solution {
public:
    Node* connect(Node* root) {
        if(!root){
            return nullptr;
        }
        // queue<Node *> que;
        // que.emplace(root);
        // while(!que.empty()){
        //     int n = que.size();
        //     vector<Node *> cur;
        //     for(int i = 0; i < n; i++){
        //         auto node = que.front();
        //         que.pop();
        //         cur.emplace_back(node);
        //         if(node->left){
        //             que.emplace(node->left);
        //         }
        //         if(node->right){
        //             que.emplace(node->right);
        //         }
        //     }
        //     for(int i = 0; i < n - 1; i++){
        //         cur[i]->next = cur[i + 1];
        //     }
        // }

        // vector<Node *> cur = {root};
        // while(!cur.empty()){
        //     vector<Node *> next;
        //     for(int i = 0; i < cur.size() - 1; i++){
        //         auto node = cur[i];
        //         node->next = cur[i + 1];
        //         if(node->left){
        //             next.emplace_back(node->left);
        //         }
        //         if(node->right){
        //             next.emplace_back(node->right);
        //         }
        //     }
        //     if(cur.back()->left){
        //         next.emplace_back(cur.back()->left);
        //     }
        //     if(cur.back()->right){
        //         next.emplace_back(cur.back()->right);
        //     }
        //     cur = move(next);
        // }

        // DFS
        // vector<Node *> pre;
        // function<void(Node *, int)> dfs = [&] (Node *cur, int depth) ->void{
        //     if(cur == nullptr){
        //         return;
        //     }
        //     if(pre.size() == depth){
        //         pre.emplace_back(cur);
        //     }else{
        //         pre[depth]->next = cur;
        //         pre[depth] = cur;
        //     }
        //     dfs(cur->left, depth + 1);
        //     dfs(cur->right, depth + 1);
        // };
        // dfs(root, 0);

        // BFS + LIST
        auto dummy = make_unique<Node>();
        auto cur = root;
        while(cur){
            dummy->next = nullptr;
            Node *tmp = dummy.get();
            while(cur){
                if(cur->left){
                    tmp->next = cur->left;
                    tmp = cur->left;
                }
                if(cur->right){
                    tmp->next = cur->right;
                    tmp = cur->right;
                }
                cur = cur->next;
            }
            cur = dummy->next;
        }
        return root;
    }
};
;