• 【LeetCode - 每日一题】1123. 最深叶节点的最近公共祖先(23.09.06)


    1123. 最深叶节点的最近公共祖先

    题意

    • 返回最深节点的最近公共祖先;
    • 每个节点的 val 互不相同;
    • 节点最多 1000 个;

    解法1 bfs + 回溯

    和经典的 LCA 不同的是,这里的对象是 若干个叶节点(1个或多个,最深的)

    • 首先将最深的叶节点找出来:bfs 广搜,用 map 存储每层的节点
    • 记录所有节点的父节点:father 数组(在 bfs 广搜的同时进行)
    • 然后回溯最深叶节点的父节点,寻找最近公共祖先(用 map 记录每个父节点的出现次数,因为回溯是倒着回溯的,所以第一个出现次数 = mp[maxLayer].size() 的一定是最近公共祖先)
    • 如果最深层叶节点只有一个,那么他的最近公共祖先是他本身。

    ps. 由于 每个节点的 val 互不相同,所以可以以 val 作为 father 数据的下标。

    /**
     * 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 {
    public:
        unordered_map<int, vector<TreeNode*> > mp;
        vector<TreeNode*> father = vector<TreeNode*>(1010);
        void bfs(TreeNode* root, int layer)
        {
            if(root == nullptr) return;
            
            mp[layer].emplace_back(root); 	// 维护每层的节点
    		
    		// 记录父节点
            if(root->left) father[root->left->val] = root;
            if(root->right) father[root->right->val] = root;
    
            bfs(root->left, layer+1);
            bfs(root->right, layer+1);
        }
        TreeNode* lcaDeepestLeaves(TreeNode* root) {
            father[root->val] = new TreeNode(-1); 	// 根节点标记
            bfs(root, 0);
    
            int maxLayer = 0;
            for(auto x : mp)
            {
                if(x.first > maxLayer) maxLayer = x.first; 	// 寻找最深层
            }
    
            if(mp[maxLayer].size() == 1) return mp[maxLayer][0]; 	// 最深叶节点只有一个
            
            unordered_map<int, int> tmp;
    
            for(auto n : mp[maxLayer])
            {
                int curNode = n->val;
                while(curNode != -1) 	// 回溯父节点
                {
                    tmp[father[curNode]->val]++;
                    if(tmp[father[curNode]->val] == mp[maxLayer].size())
                    {
                        return father[curNode];                              
                    }
                    curNode = father[curNode]->val;
                }
            }
            return nullptr;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    复杂度

    时间复杂度:O(n),bfs 遍历每个节点。
    空间复杂度:O(d),递归栈的大小等于树的深度。

    解法2 递归

    比较左右子树的深度:

    • 若左子树深,则 lca 为左子树的 lca;
    • 若右子树深,则 lca 为右子树的 lca;
    • 若左右子树一样深,则 lca 为当前节点。
    /**
     * 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 {
    public:
        pair<TreeNode*, int> f(TreeNode* root)
        {
            if(root == nullptr) return {root, 0};
    
            auto left = f(root->left);
            auto right = f(root->right);
    
            if(left.second > right.second)  // 左子树深
            {
                return {left.first, left.second + 1};
            }
            if(left.second < right.second)  // 右子树深
            {
                return {right.first, right.second + 1};
            }
            return {root, left.second + 1};
        }
        TreeNode* lcaDeepestLeaves(TreeNode* root) {
            return f(root).first;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    复杂度

    时间复杂度:O(n),遍历每个节点。
    空间复杂度:O(d),递归栈的大小等于树的深度。


  • 相关阅读:
    基于web在线餐饮网站的设计与实现——蛋糕甜品店铺(HTML+CSS+JavaScript)
    CMU/MIT/清华/Umass提出生成式机器人智能体RoboGen
    计算机视觉CV领域中多尺度特征的概念
    postgresql
    部署 Wi-Fi 6 之前需要回答的 13 个问题
    产品经理的秘密武器:提高效率的 6 种软件工具
    CMSC5707-高级人工智能之自编码器Auto-encoders
    如何通过A/B测试提升Push推送消息点击率?
    Hamiton图系列文章 (2) Hamilton图道路矩阵类的乘法设计
    Kafka 单机和集群环境部署教程
  • 原文地址:https://blog.csdn.net/weixin_43736572/article/details/132707929