二叉树高频题(上)

二叉树高频题(上)

102. 二叉树的层序遍历

#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;

    TreeNode() : val(0), left(nullptr), right(nullptr) {}

    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}

    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode *root) {
        if (root == nullptr) return vector<vector<int>>();
        vector<vector<int>> res;
        queue<TreeNode *> q;
        q.emplace(root);

        while (!q.empty()) {
            int len = q.size();
            vector<int> curLever;
            // 一层一层遍历
            for (int i = 0; i < len; ++i) {
                TreeNode *node = q.front();
                q.pop();
                curLever.emplace_back(node->val);
                // 下层节点入队
                if (node->left != nullptr) q.emplace(node->left);
                if (node->right != nullptr) q.emplace(node->right);
            }
            res.emplace_back(curLever);
        }
        return res;
    }
};

103. 二叉树的锯齿形层序遍历

#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;

    TreeNode() : val(0), left(nullptr), right(nullptr) {}

    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}

    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode *root) {
        if (root == nullptr) return vector<vector<int>>();
        vector<vector<int>> res;
        stack<int> stk;
        queue<TreeNode *> q;
        q.emplace(root);
        bool flag = true;

        while (!q.empty()) {
            int len = q.size();
            vector<int> curLever;
            // 一层一层遍历
            for (int i = 0; i < len; ++i) {
                TreeNode *node = q.front();
                q.pop();
                if (flag == true) {
                    curLever.emplace_back(node->val);
                } else {
                    stk.emplace(node->val);
                }
                // 下层节点入队
                if (node->left != nullptr) q.emplace(node->left);
                if (node->right != nullptr) q.emplace(node->right);
            }
            flag = !flag;
            while (!stk.empty()) {
                curLever.emplace_back(stk.top());
                stk.pop();
            }
            res.emplace_back(curLever);
        }
        return res;
    }
};

662. 二叉树最大宽度

  • 层序遍历
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;

    TreeNode() : val(0), left(nullptr), right(nullptr) {}

    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}

    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    int widthOfBinaryTree(TreeNode *root) {
        if (root == nullptr) return 1;
        int res = 1;
        // 给节点加上编号,有溢出的可能
        queue<pair<TreeNode *, unsigned long long>> q;
        q.emplace(make_pair(root, 0));

        while (!q.empty()) {
            int len = q.size();
            // 当前层最左和最右的节点编号
            unsigned long long firstIndex;
            unsigned long long lastIndex;
            // 一层一层遍历
            for (int i = 0; i < len; ++i) {
                auto p = q.front();
                q.pop();
                TreeNode *node = p.first;
                unsigned long long index = p.second;
                if (i == 0) firstIndex = index;
                if (i == len - 1) lastIndex = index;
                // 下层节点入队
                if (node->left != nullptr) q.emplace(make_pair(node->left, 2 * index + 1));
                if (node->right != nullptr) q.emplace(make_pair(node->right, 2 * index + 2));
            }
            // 更新最大宽度
            res = lastIndex - firstIndex + 1 > res ? lastIndex - firstIndex + 1 : res;
        }
        return res;
    }
};
  • DFS
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <unordered_map>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;

    TreeNode() : val(0), left(nullptr), right(nullptr) {}

    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}

    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    unsigned long long result = 0;
    // <level 层, level 层最左节点的编号>
    unordered_map<int, unsigned long long> map;

    int widthOfBinaryTree(TreeNode *root) {
        dfs(root, 0, 0);
        return result;
    }

    void dfs(TreeNode *node, unsigned long long nodeIndex, int level) {
        if (node == nullptr) return;
        if (map.count(level) == 0) map[level] = nodeIndex;
        result = max(result, nodeIndex - map[level] + 1);
        dfs(node->left, 2 * nodeIndex + 1, level + 1);
        dfs(node->right, 2 * nodeIndex + 2, level + 1);
    }
};

104. 二叉树的最大深度

  • 层序遍历
#include <vector>
#include <algorithm>

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;

    TreeNode() : val(0), left(nullptr), right(nullptr) {}

    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}

    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    int maxDepth(TreeNode *root) {
        if (root == nullptr) return 0;
        int depth = 0;
        const int size = 5002;
        // 循环队列
        struct TreeNode *queue[size];
        int front = 0, rear = 0;
        queue[rear++] = root;

        while (front != rear) {
            int count = (rear - front + size) % size;
            // 一层加一次
            depth++;
            while (count-- > 0) {
                struct TreeNode *node = queue[(front++) % size];
                if (node->left != nullptr) queue[(rear++) % size] = node->left;
                if (node->right != nullptr) queue[(rear++) % size] = node->right;
            }
        }
        return depth;
    }
};
  • 递归
#include <vector>
#include <algorithm>

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;

    TreeNode() : val(0), left(nullptr), right(nullptr) {}

    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}

    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    int maxDepth(TreeNode *root) {
        if (root == nullptr) return 0;
        int left = maxDepth(root->left);
        int right = maxDepth(root->right);
        return (left > right ? left : right) + 1;
    }
};

111. 二叉树的最小深度

  • 层序遍历
#include <vector>
#include <algorithm>

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;

    TreeNode() : val(0), left(nullptr), right(nullptr) {}

    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}

    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    int minDepth(TreeNode *root) {
        if (root == nullptr) return 0;
        const int size = 50002;
        struct TreeNode *queue[size];
        int front = 0;
        int rear = 0;
        int depth = 0;
        queue[rear++] = root;

        while (front != rear) {
            int count = (rear - front + size) % size;
            depth++;
            while (count-- > 0) {
                struct TreeNode *node = queue[(front++) % size];
                // 首次遇到没有孩子的时候,就是最小深度
                if (node->left == nullptr && node->right == nullptr)
                    return depth;
                if (node->left != nullptr)queue[(rear++) % size] = node->left;
                if (node->right != nullptr) queue[(rear++) % size] = node->right;
            }
        }

        return depth;
    }
};
  • DFS
#include <vector>
#include <algorithm>

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;

    TreeNode() : val(0), left(nullptr), right(nullptr) {}

    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}

    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    int minDp;

    void dfs(TreeNode *node, int currentDepth) {
        if (node == nullptr) return;
        currentDepth++;
        // 更新最小深度
        if ((node->left == nullptr && node->right == nullptr)
            && currentDepth < minDp)
            minDp = currentDepth;
        dfs(node->left, currentDepth);
        dfs(node->right, currentDepth);
    }

    int minDepth(TreeNode *root) {
        if (root == nullptr) return 0;
        minDp = INT_MAX;
        dfs(root, 0);
        return minDp;
    }
};
  • 递归
#include <vector>
#include <algorithm>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;

    TreeNode() : val(0), left(nullptr), right(nullptr) {}

    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}

    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    // 自底向上
    int minDepth(TreeNode *root) {
        if (root == nullptr) return 0;
        if (root->left == nullptr && root->right == nullptr) return 1;
        int lD = INT_MAX;
        int rD = INT_MAX;
        if (root->left != nullptr) lD = minDepth(root->left);
        if (root->right != nullptr) rD = minDepth(root->right);
        return min(lD, rD) + 1;
    }
};

297. 二叉树的先序列化与反序列化

  • 二叉树可以通过先序、后序或者按层遍历的方式序列化和反序列化
  • 但是,二叉树无法通过中序遍历的方式实现序列化和反序列化
  • 因为不同的两棵树,可能得到同样的中序序列,即便补了空位置也可能一样。
#include <vector>
#include <algorithm>
#include <string>
#include <regex>
#include <iostream>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;

    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

class Codec {
public:
    int cnt;

    void encode(TreeNode *root, string &str) {
        if (root == nullptr) {
            str.append("#,");
            return;
        }
        str.append(to_string(root->val) + ",");
        encode(root->left, str);
        encode(root->right, str);
    }

    TreeNode *decode(vector<string> &vals) {
        string cur = vals[cnt++];
        if (cur == "#") return nullptr;
        TreeNode *node = new TreeNode(stoi(cur));
        node->left = decode(vals);
        node->right = decode(vals);
        return node;
    }

    string serialize(TreeNode *root) {
        string res = "";
        encode(root, res);
        return res;
    }

    TreeNode *deserialize(string data) {
        vector<string> vals = split(data, ",");
        cnt = 0;
        return decode(vals);
    }

    vector<string> split(const string &str, const string &split) {
        vector<string> res;
        // 匹配 split
        regex reg(split);
        sregex_token_iterator pos(str.begin(), str.end(), reg, -1);
        for (decltype(pos) end; pos != end; ++pos)
            res.push_back(pos->str());
        return res;
    }
};

297. 二叉树的层序列化与反序列化

#include <vector>
#include <algorithm>
#include <string>
#include <regex>
#include <iostream>
#include <queue>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;

    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};

class Codec {
public:
    // 层序遍历
    void encode(TreeNode *root, string &str) {
        queue<TreeNode *> q;
        q.emplace(root);

        while (!q.empty()) {
            TreeNode *cur = q.front();
            q.pop();
            if (cur == nullptr) {
                str.append("#,");
            } else {
                str.append(to_string(cur->val) + ",");
                // 空指针也加入
                q.emplace(cur->left);
                q.emplace(cur->right);
            }
        }
    }

    TreeNode *generate(string val) {
        return val == "#" ? nullptr : new TreeNode(stoi(val));
    }

    TreeNode *decode(vector<string> &vals) {
        int cnt = 0;
        TreeNode *root = generate(vals[cnt++]);
        queue<TreeNode *> q;
        q.emplace(root);

        while (!q.empty()) {
            TreeNode *node = q.front();
            q.pop();
            if (node == nullptr) continue;
            node->left = generate(vals[cnt++]);
            node->right = generate(vals[cnt++]);
            if (node->left != nullptr) q.emplace(node->left);
            if (node->right != nullptr) q.emplace(node->right);
        }
        return root;
    }

    string serialize(TreeNode *root) {
        string res = "";
        encode(root, res);
        return res;
    }

    TreeNode *deserialize(string data) {
        vector<string> vals = split(data, ",");
        return decode(vals);
    }

    vector<string> split(const string &str, const string &split) {
        vector<string> res;
        // 匹配 split
        regex reg(split);
        sregex_token_iterator pos(str.begin(), str.end(), reg, -1);
        for (decltype(pos) end; pos != end; ++pos)
            res.push_back(pos->str());
        return res;
    }
};

105. 从前序与中序遍历序列构造二叉树

  • todo

  • 利用先序与中序遍历序列构造二叉树

  • 无重复值

#include <vector>
#include <algorithm>
#include <string>
#include <regex>
#include <iostream>
#include <stack>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;

    TreeNode() : val(0), left(nullptr), right(nullptr) {}

    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}

    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) {
        if (preorder.size() == 0) return nullptr;
        int pre = 0;
        int in = 0;
        stack<TreeNode *> stk;
        // 先序遍历的第一个值作为根节点
        TreeNode *curRoot = new TreeNode(preorder[pre++]);
        TreeNode *res = curRoot;
        stk.emplace(curRoot);

        for (; pre < preorder.size(); pre++) {
            if (curRoot->val == inorder[in]) {
                // 当前根节点刚好是中序序列的首个节点,说明当前根节点没有左子树
                while (!stk.empty() && stk.top()->val == inorder[in]) {
                    curRoot = stk.top();
                    stk.pop();
                    in++;
                }
                TreeNode *node = new TreeNode(preorder[pre]);
                curRoot->right = node;
                curRoot = curRoot->right;
                stk.emplace(curRoot);
            } else {
                // 当前根节点有左子树,且就是先序序列中当前根节点后面的一个节点
                TreeNode *node = new TreeNode(preorder[pre]);
                curRoot->left = node;
                // 左子树根节点入栈
                curRoot = curRoot->left;
                stk.emplace(curRoot);
            }
        }
        return res;
    }
};
  • 递归
#include <vector>
#include <algorithm>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;

    TreeNode() : val(0), left(nullptr), right(nullptr) {}

    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}

    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    int pre;
    int in;

    TreeNode *generate(vector<int> &preorder, vector<int> &inorder, int stop) {
        if (pre == preorder.size()) return nullptr;
        if (inorder[in] == stop) {
            // 说明以 stop 为根节点的左子树已经生成完毕
            in++;
            return nullptr;
        }
        int rootVal = preorder[pre++];
        TreeNode *root = new TreeNode(rootVal);
        // 只有左子树生成完毕,才会遇到他的 stop,也就是左子树的父节点
        root->left = generate(preorder, inorder, rootVal);
        // root 子树是以 stop 为父节点的左子树
        root->right = generate(preorder, inorder, stop);
        return root;
    }

    TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) {
        pre = 0;
        in = 0;
        return generate(preorder, inorder, INT_MAX);
    }
};
  • 递归
#include <vector>
#include <algorithm>
#include <string>
#include <regex>
#include <iostream>
#include <stack>
#include <unordered_map>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;

    TreeNode() : val(0), left(nullptr), right(nullptr) {}

    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}

    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};


class Solution {
public:
    unordered_map<int, int> map;

    TreeNode *generate(vector<int> &preorder, int rootIndex, int left, int right) {
        if (left > right) return nullptr;
        TreeNode *node = new TreeNode(preorder[rootIndex]);
        // 当前根节点在中序序列中的位置
        int in = map[preorder[rootIndex]];
        // 左子树递归,左子树的根节点在先序序列中的位置为 rootIndex + 1
        // 左子树的节点在中序序列的位置为 [left, in - 1]
        node->left = generate(preorder, rootIndex + 1, left, in - 1);
        // 右子树递归,右子树的根节点在先序序列中的位置为 rootIndex + in - left + 1
        // 右子树的节点在中序序列的位置为 [in + 1, right]
        node->right = generate(preorder, rootIndex + in - left + 1, in + 1, right);
        return node;
    }

    TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) {
        // 记录位置
        for (int i = 0; i < inorder.size(); i++)
            map[inorder[i]] = i;
        return generate(preorder, 0, 0, inorder.size() - 1);
    }
};

958. 二叉树的完全性检验

#include <vector>
#include <algorithm>
#include <string>
#include <regex>
#include <iostream>
#include <stack>
#include <queue>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;

    TreeNode() : val(0), left(nullptr), right(nullptr) {}

    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}

    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    bool isCompleteTree(TreeNode *root) {
        if (root == nullptr) return true;
        queue<TreeNode *> q;
        q.emplace(root);
        // 是否已经遇到第一个孩子不全的节点
        bool leaf = false;
        while (!q.empty()) {
            TreeNode *node = q.front();
            q.pop();
            // 已经遇到第一个孩子不全的节点,如果后面遇到的不是叶子节点,说明不是完全二叉树
            if (leaf == true
                && (node->left != nullptr || node->right != nullptr))
                return false;
            // 只有右孩子肯定不是完全二叉树
            if (node->left == nullptr && node->right != nullptr) return false;
            // 入队
            if (node->left != nullptr) q.emplace(node->left);
            if (node->right != nullptr) q.emplace(node->right);
            // 标记已经遇到
            if (node->left == nullptr || node->right == nullptr) leaf = true;
        }
        return true;
    }
};

222. 完全二叉树的节点个数

#include <vector>
#include <algorithm>
#include <string>
#include <regex>
#include <iostream>
#include <stack>
#include <queue>
#include <valarray>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;

    TreeNode() : val(0), left(nullptr), right(nullptr) {}

    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}

    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    // 完全二叉树的深度
    int getDepth(TreeNode *root) {
        int depth = 0;
        while (root != nullptr) {
            depth++;
            root = root->left;
        }
        return depth;
    }

    // 时间复杂度 O(logn ^ 2)
    int countNodes(TreeNode *root) {
        if (root == nullptr) return 0;
        int leftDepth = getDepth(root->left);
        int rightDepth = getDepth(root->right);
        int leftCnt = 0;
        int rightCnt = 0;

        if (leftDepth == rightDepth) {
            // 左子树必满
            leftCnt = pow(2, leftDepth) - 1;
            // 递归计算右子树
            rightCnt = countNodes(root->right);
        } else {
            // 右子树必满
            rightCnt = pow(2, rightDepth) - 1;
            // 递归计算左子树
            leftCnt = countNodes(root->left);
        }

        return leftCnt + rightCnt + 1;
    }
};
posted @ 2024-09-29 20:40  n1ce2cv  阅读(5)  评论(0编辑  收藏  举报