C语言刷二叉树(三)提高部分

236. 二叉树的最近公共祖先

 /*
 * 1.后序遍历
 * 2.左子树和右子树每颗树都完整的遍历1遍
 * 3.回溯,利用左子树和右子树的返回值,来判断最近公共祖先
 */
struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) 
{
    if (root == p || root == q || root == NULL) return root;
    
    struct TreeNode *left = lowestCommonAncestor(root->left, p, q);
    struct TreeNode *right = lowestCommonAncestor(root->right, p, q);

    if (left != NULL && right != NULL) return root;
    if (left == NULL && right != NULL) return right;
    return left;
}

 

归纳如下三点:

  1. 求最小公共祖先,需要从底向上遍历,那么二叉树,只能通过后序遍历(即:回溯)实现从低向上的遍历方式。

  2. 在回溯的过程中,必然要遍历整棵二叉树,即使已经找到结果了,依然要把其他节点遍历完,因为要使用递归函数的返回值(也就是代码中的left和right)做逻辑判断。

  3. 要理解如果返回值left为空,right不为空为什么要返回right,为什么可以用返回right传给上一层结果。

 

235. 二叉搜索树的最近公共祖先

/* 解法一:利用二叉搜索树的性质 */
struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) 
{
    int leftVal = p->val < q->val ? p->val : q->val;
    int rightVal = p->val > q->val ? p->val : q->val;
    while (root != NULL) {
        if (root->val > leftVal && root->val < rightVal) {
            return root;
        } else if (root->val == leftVal || root->val == rightVal) {
            return root;
        } else if (root->val > rightVal) {
            root = root->left;
        } else {
            root = root->right;
        }
    }
    return NULL;
}


/* 解法二:暴力解法,没有利用二叉搜索树的特性 */
struct TreeNode* lowestCommonAncestor(struct TreeNode* root, struct TreeNode* p, struct TreeNode* q) 
{
    if (root == NULL || root == p || root == q) return root;

    struct TreeNode *left = lowestCommonAncestor(root->left, p, q);
    struct TreeNode *right = lowestCommonAncestor(root->right, p, q);
    
    if (left != NULL && right != NULL) {
        return root;
    } else if (left == NULL && right != NULL) {
        return right;
    }
    return left;
}

 

posted @ 2022-10-09 16:44  胖白白  阅读(22)  评论(0编辑  收藏  举报