【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;
    }
};

复杂度

时间复杂度: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;
    }
};

复杂度

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


你可能感兴趣的:(每日一题,c++,leetcode,leetcode,每日一题,c++)