• 236. Lowest Common Ancestor of a Binary Tree


    问题描述:

    Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.

    According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”

    Given the following binary tree:  root = [3,5,1,6,2,0,8,null,null,7,4]

            _______3______
           /              
        ___5__          ___1__
       /              /      
       6      _2       0       8
             /  
             7   4
    

    Example 1:

    Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
    Output: 3
    Explanation: The LCA of of nodes 5 and 1 is 3.
    

    Example 2:

    Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
    Output: 5
    Explanation: The LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself
                 according to the LCA definition.

    Note:

    • All of the nodes' values will be unique.
    • p and q are different and both values will exist in the binary tree.

    解题思路:

    找两个节点最低的祖先节点,并且一个节点可以成为它自己的祖先节点。

    我们可以先找到其中一个节点,这个时候我们需要遍历树,我在这里采用的是使用栈的前序遍历,当该节点值等于目标节点其中一个的值时,跳出循环。

    找到的点为findN,未找到的为targetN

    这个时候我们可以考虑两个点之间的关系:

      1. targetN是findN的子节点

      2.targetN不是findN的子节点

    所以我们首先需要搜寻findN的子树,若包含targetN,则直接返回findN

    若不包含,则需要从栈内弹出一个节点并且搜寻它的子树。

    这里我们可以进行剪枝,因为此时栈顶是我们findN的父节点,并且我们已经搜索过了findN的子树,我们就不需要搜索它的左子树了。

    但是targetN很可能是findN的父节点, 所以我们先要对栈顶值进行检查,如果不是我们想要找的值,则检查它的右子树

    代码:

    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
            stack<TreeNode*> stk;
            int restNode = 2;
            TreeNode* cur = root;
            while(cur || !stk.empty()){
                if(cur){
                    if(cur->val == p->val || cur->val == q->val){
                        break;
                    }
                    stk.push(cur);
                    cur = cur->left;
                }else{
                    cur = stk.top();
                    stk.pop();
                    cur = cur->right;
                }
            }
            TreeNode* targetN = cur->val == p->val ? q : p;
            TreeNode* findN = cur;
            if(containsNode(cur, targetN)){
                return cur;
            }
            while(!stk.empty()){
                cur = stk.top();
                if(cur->val == targetN->val)
                    break;
                stk.pop();
                if(containsNode(cur->right, targetN))
                    break;
            }
            return cur;
        }
        bool containsNode(TreeNode* root, TreeNode* t){
            if(!root)
                return false;
            stack<TreeNode*> stk;
            TreeNode* cur = root;
            while(cur || !stk.empty()){
                if(cur){
                    if(cur->val == t->val)
                        return true;
                    stk.push(cur);
                    cur = cur->left;
                }else{
                    cur = stk.top();
                    stk.pop();
                    cur = cur->right;
                }
            }
            return false;
        }
    };
  • 相关阅读:
    夺命雷公狗---微信开发22----微信客户端下载多媒体文件
    夺命雷公狗---微信开发21----通过程序进行下载多媒体文件
    夺命雷公狗---微信开发20----编写程序进行上传多媒体文件
    夺命雷公狗---微信开发19----使用网页调试工具调试该接口进行文件的上传与下载
    夺命雷公狗---微信开发18----删除自定义菜单
    夺命雷公狗---微信开发17----自定义菜单的事件推送,响应菜单的CLICK
    夺命雷公狗---微信开发16----自定义菜单的查询
    夺命雷公狗---微信开发15----编写进行创建自定义菜单
    夺命雷公狗---微信开发14----用网页调试工具调试自定义菜单接口
    夺命雷公狗---微信开发13----获取access_token
  • 原文地址:https://www.cnblogs.com/yaoyudadudu/p/9189715.html
Copyright © 2020-2023  润新知