LC 6223.移除子树后的二叉树高度(dp ||dfs序)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LC 6223.移除子树后的二叉树高度(dp ||dfs序)相关的知识,希望对你有一定的参考价值。

LC 6223.移除子树后的二叉树高度(dp ||dfs序)

思路1.dfs序

显然子树问题可以用dfs序转成区间问题。

本题可以转的原因,删除一个子树,相当删除一个子树,而除了该子树外的其他点都可以从根节点走到(题目保证根不会被删)。因此每次询问就剩下一个前缀和后缀,取他们两的最大值就是答案,这个值定义为每个结点的深度。

时间复杂度: O ( n ) O(n) O(n)

/**
 * Definition for a binary tree node.
 * 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 
    int n = 0, clk = 0;
    vector<int> A, L, R;

    void dfs(TreeNode *node, int d) 
        // 没有输入 n,只好动态计算 n 的大小并扩充列表...
        int idx = node->val;
        n = max(idx, n);
        while (A.size() <= n) A.push_back(0), L.push_back(0), R.push_back(0);

        // node 是第 clk 个被访问的点
        clk++;
        // A[i] 表示第 i 个被访问的点的深度
        A[clk] = d;
        // L[i] 表示第 i 个点的子树对应的连续区间的左端点
        L[idx] = clk;

        // DFS 子树
        if (node->left != nullptr) dfs(node->left, d + 1);
        if (node->right != nullptr) dfs(node->right, d + 1);

        // R[i] 表示第 i 个点的子树对应的连续区间的右端点
        R[idx] = clk;
    

public:
    vector<int> treeQueries(TreeNode* root, vector<int>& queries) 
        dfs(root, 0);

        // f[i] 表示 max(A[1], A[2], ..., A[i])
        // g[i] 表示 max(A[n], A[n - 1], ..., A[i])
        vector<int> f(n + 2), g(n + 2);
        for (int i = 1; i <= n; i++) f[i] = max(f[i - 1], A[i]);
        for (int i = n; i > 0; i--) g[i] = max(g[i + 1], A[i]);

        vector<int> ans;
        // 树上询问转为区间询问处理
        for (int x : queries) ans.push_back(max(f[L[x] - 1], g[R[x] + 1]));
        return ans;
    
;

思路2 dp

先预处理出每个子树的最大高度,这个可以递归。

然后dfs,从根开始枚举删掉某个子树后的答案,显然就是从根开始到此节点的深度+val(另一个结点) (之前预处理的高度)

时间复杂度: O ( n ) O(n) O(n)

class Solution 
public:
    vector<int> treeQueries(TreeNode *root, vector<int> &queries) 
        unordered_map<TreeNode*, int> height; // 每棵子树的高度
        function<int(TreeNode*)> get_height = [&](TreeNode *node) -> int 
            return node ? height[node] = 1 + max(get_height(node->left), get_height(node->right)) : 0;
        ;
        get_height(root);

        int res[height.size() + 1]; // 每个节点的答案
        function<void(TreeNode*, int, int)> dfs = [&](TreeNode *node, int depth, int rest_h) 
            if (node == nullptr) return;
            ++depth;
            res[node->val] = rest_h;
            dfs(node->left, depth, max(rest_h, depth + height[node->right]));
            dfs(node->right, depth, max(rest_h, depth + height[node->left]));
        ;
        dfs(root, -1, 0);

        for (auto &q : queries) q = res[q];
        return queries;
    
;

以上是关于LC 6223.移除子树后的二叉树高度(dp ||dfs序)的主要内容,如果未能解决你的问题,请参考以下文章

(leetcode) 2458. 移除子树后的二叉树高度

(leetcode) 2458. 移除子树后的二叉树高度

树-二叉树的基本概念

平衡二叉树

平衡二叉树详解——PHP代码实现

PHP代码实现平衡二叉树详解