二叉树常见基础问题

1.普通二叉树的LCA如何求(朴素做法)

两种情况

第一种,p和q是分开的。
第二种,其中一个是lca。

从根节点开始遍历,如果碰到了p或q那么这个节点就是lca,如果一个节点左右子树均有p或q,那么这个节点是lca。

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root==NULL||root==p||root==q)
        {
            return root;
        }
        TreeNode* l=lowestCommonAncestor(root->left,p,q);
        TreeNode* r=lowestCommonAncestor(root->right,p,q);
        if(l==NULL&&r==NULL)
        {
            return NULL;
        }
        if(l!=NULL&&r!=NULL)
        {
            return root;
        }
        return l!=NULL?l:r;
    }
};

2.求二叉搜索树的lca

二叉搜索树,指的是任何一个节点左子树的数字必然小于这个节点,而右子树的数字必然大于这个节点。

利用这个性质,我们在找lca的时候可以更方便一些,假设两个节点是p,q,且p<q,那么如果遍历到一个点,这个节点<p,那么显然lca一定在右子树上,如果这个节点>q,那么lca一定在左子树上,如果p<该节点<q,那么这个节点就是lca.

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        while (root->val != p->val && root->val != q->val) {
            if (min(p->val, q->val) < root->val &&
                max(p->val, q->val) > root->val) {
                break;
            }
            if (root->val < min(p->val, q->val)) {
                root = root->right;
            } else {
                root = root->left;
            }
        }
        return root;
    }
};

3.给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。

类似于dfs,需要回溯,准备一个二维答案数组,然后从根节点开始dfs,碰到叶子节点就判断是否满足条件,如果满足就将临时路径数组加入答案数组。

class Solution {
public:
    void f(TreeNode* root, int aim, int sum, vector<vector<int>>& ans,
           vector<int>& p) {
        if (root->left == nullptr && root->right == nullptr) {
            if (sum + root->val == aim) {
                p.push_back(root->val);
                ans.push_back(p);
                p.pop_back();
            }
        } else {
            p.push_back(root->val);
            if (root->left != nullptr) {
                f(root->left, aim, sum + root->val, ans, p);
            }
            if (root->right != nullptr) {
                f(root->right, aim, sum + root->val, ans, p);
            }
            p.pop_back();
        }
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        vector<vector<int>> ans;
        if (root != nullptr) {
            vector<int> p;
            f(root, targetSum, 0, ans, p);
        }
        return ans;
    }
};

4.判断一个二叉树是否为平衡二叉树

平衡二叉树,即任何一个节点的左右子树高度差不超过1.

由此性质,我们可以通过递归判断。

class Solution {
public:
    bool ok = true;
    int f(TreeNode* root) {
        if (!ok || root == nullptr) {
            return 0;
        }
        int l = f(root->left);
        int r = f(root->right);
        if (abs(l - r) > 1) {
            ok = false;
        }
        return max(l, r) + 1;
    }
    bool isBalanced(TreeNode* root) {

        int ans = f(root);
        return ok;
    }
};

5.判断一个二叉树是不是搜索二叉树

方法:通过中序遍历的方式,遍历数字应该是递增的。

class Solution {
public:
    bool isValidBST(TreeNode* root) {
        TreeNode* mi = nullptr;
        stack<TreeNode*> p;
        while ((!p.empty()) || root != nullptr) {
            if (root != nullptr) {
                p.push(root);
                root = root->left;
            } else {
                root = p.top();
                p.pop();
                if (mi != nullptr && mi->val >= root->val) {
                    return false;
                }
                mi = root;
                root = root->right;
            }
        }
        return true;
    }
};

6.修剪搜索二叉树

https://leetcode.cn/problems/trim-a-binary-search-tree/

采用递归的方法,先判断当前节点是否满足条件,不满足则向下递归,如果满足条件,那么修改左右孩子的值,返回即可。

class Solution {
public:
    TreeNode* trimBST(TreeNode* root, int low, int high) {
        if (root == nullptr) {
            return nullptr;
        }
        if (root->val > high) {
            return trimBST(root->left, low, high);
        }
        if (root->val < low) {
            return trimBST(root->right, low, high);
        }
        root->left = trimBST(root->left, low, high);
        root->right = trimBST(root->right, low, high);
        return root;
    }
};

7.二叉树上的打家劫舍问题

https://leetcode.cn/problems/house-robber-iii/description/

感觉有点树形dp的影子,定义两个全局变量yes,no,每次完成一个函数,yes变为选这个点获得的最大值,no变为不选这个点获得的最大值。

class Solution {
public:
    int yes = 0, no = 0;
    void f(TreeNode* cur) {
        if (cur == nullptr) {
            yes = 0, no = 0;
            return;
        }
        int y = cur->val;
        int n = 0;
        f(cur->left);
        y += no;
        n += max(yes, no);
        f(cur->right);
        y += no;
        n += max(yes, no);
        yes = y;
        no = n;
    }
    int rob(TreeNode* root) {
        f(root);
        return max(yes, no);
    }
};
posted @ 2026-03-03 18:45  Lambda_L  阅读(2)  评论(0)    收藏  举报