JHHK

欢迎来到我的个人网站
行者常至 为者常成

【题目】7、二叉树

目录

二叉树的绝大部分题目都可以直接通过递归 遍历解决
前序遍历
中序遍历
后序遍历
层序遍历

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

题目描述

236. 二叉树的最近公共祖先
 
 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,
 最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

 例如,给定如下二叉树:  root = [3,5,1,6,2,0,8,null,null,7,4]

 示例 1:
 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
 输出: 3
 解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
 
 示例 2:
 输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
 输出: 5
 解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。
  
 说明:
 所有节点的值都是唯一的。
 p、q 为不同节点且均存在于给定的二叉树中

 来源:力扣(LeetCode)
 链接:https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-tree
 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题目实现

class Solution {
public:
    
    /**
      * 去以root为根节点的二叉树中查找p、q的最近公共祖先
      * ① 如果p、q同时存在于这棵二叉树中,就能成功返回它们的最近公共祖先
      * ② 如果p、q都不存在于这棵二叉树中,返回null
      * ③ 如果只有p存在于这棵二叉树中,返回p
      * ④ 如果只有q存在于这棵二叉树中,返回q
      */
    
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        
        if (root == nullptr || root == p || root == q) return root;
        
        // 去以root.left为根节点的二叉树中查找p、q的最近公共祖先
        TreeNode * left = lowestCommonAncestor(root->left, p, q);
        // 去以root.right为根节点的二叉树中查找p、q的最近公共祖先
        TreeNode * right = lowestCommonAncestor(root->right, p, q);
        
        if (left != nullptr && right != nullptr) return root;
        
        return (left != nullptr) ? left : right;
    }
};

99. 恢复二叉搜索树

题目描述

99. 恢复二叉搜索树
 
 给你二叉搜索树的根节点 root ,该树中的两个节点被错误地交换。请在不改变其结构的情况下,恢复这棵树。
 进阶:使用 O(n) 空间复杂度的解法很容易实现。你能想出一个只使用常数空间的解决方案吗?
 
 示例 1:
 输入:root = [1,3,null,null,2]
 输出:[3,1,null,null,2]
 解释:3 不能是 1 左孩子,因为 3 > 1 。交换 1 和 3 使二叉搜索树有效。
 
 
 示例 2:
 输入:root = [3,1,4,null,null,2]
 输出:[2,1,4,null,null,3]
 解释:2 不能在 3 的右子树中,因为 2 < 3 。交换 2 和 3 使二叉搜索树有效。
  

 提示:
 树上节点的数目在范围 [2, 1000] 内
 -231 <= Node.val <= 231 - 1

 来源:力扣(LeetCode)
 链接:https://leetcode-cn.com/problems/recover-binary-search-tree
 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题目实现 - 方式一

class Solution1 {
public:
    //上一次中序遍历过的节点
    TreeNode * prev;
    //第一个错误节点
    TreeNode * first;
    //第二个错误节点
    TreeNode * second;
    
    void recoverTree(TreeNode* root) {
        //中序遍历查找错误节点
        inorder(root);
        
        //交换2个错误节点的值
        int temp = first->val;
        first->val = second->val;
        second->val = temp;
    }
    
    
    //中序遍历
    void inorder(TreeNode* root){
        if (root == nullptr) return;
        inorder(root->left);
        find(root);
        inorder(root->right);
    }
    
    
    //查找错误节点
    void find(TreeNode* node){
        //出现了逆序对
        if (prev != nullptr && prev->val > node->val) {
            //第二个错误节点:最后一个逆序对中较小的那个节点
            second = node;
            
            //第1个错误节点:第一个逆序对中较大的那个节点
            if (first != nullptr) return;
            first = prev;
        }
        prev = node;
    }
};

题目实现 - 方式二

//morris方法遍历二叉树
class Solution {
public:
    //上一次中序遍历过的节点
    TreeNode * prev;
    //第一个错误节点
    TreeNode * first;
    //第二个错误节点
    TreeNode * second;
    
    void recoverTree(TreeNode* root) {
        //中序遍历查找错误节点
        morris(root);
        
        //交换2个错误节点的值
        int temp = first->val;
        first->val = second->val;
        second->val = temp;
    }
    
    
    //中序遍历
    void morris(TreeNode* root){
        TreeNode * node = root;
        
        while (node != nullptr) {
            if (node->left !=nullptr) {
                
                // 找到前驱节点(predecessor)、后继节点(successor)
                TreeNode * pred = node->left;
                while (pred->right != nullptr && pred->right != node) {
                    pred = pred->right;
                }
                
                if (pred->right == nullptr) {
                    pred->right = node;
                    node = node->left;
                } else { // pred.right == node
                    find(node);
                    pred->right = nullptr;
                    node = node->right;
                }
            }else{
                find(node);
                node = node->right;
            }
        }
    }
    
    
    //查找错误节点
    void find(TreeNode* node){
        //出现了逆序对
        if (prev != nullptr && prev->val > node->val) {
            //第二个错误节点:最后一个逆序对中较小的那个节点
            second = node;
            
            //第1个错误节点:第一个逆序对中较大的那个节点
            if (first != nullptr) return;
            first = prev;
        }
        prev = node;
    }
};

333. 最大BST子树

题目实现

class Solution1 {
 
    bool isBST(TreeNode * root){
        return false;
    }
    
    
    int nodesCount(TreeNode * root){
        return 0;
    }
    
public:
    int largestBSTSubtree(TreeNode*root){
        if (root == nullptr) return 0;
        if (isBST(root)) return nodesCount(root);
        return max(largestBSTSubtree(root->left), largestBSTSubtree(root->right));
    }
};
class Solution {
    class Info{
    public:
        /** 根节点 */
        TreeNode* root;
        /** 节点总数 */
        int size;
        /** 最大值 */
        int max;
        /** 最小值 */
        int min;
        
        Info(TreeNode*root,int size,int max,int min){
            this->root = root;
            this->size = size;
            this->max = max;
            this->min = min;
        }
    };
    
    
    Info* getInfo(TreeNode* root){
        
        if (root == nullptr) return nullptr;
        
        // li(left info):左子树的最大BST子树信息
        Info* li = getInfo(root->left);
        
        // ri(right info):右子树的最大BST子树信息
        Info* ri = getInfo(root->right);
        
        /*
         有4种情况,以root为根节点的二叉树就是一棵BST,最大BST子树就是其本身
         ① li != null && ri != null
         && li.root == root.left && root.val > li.max
         && ri.root == root.right && root.val < ri.min
         
         ② li != null && ri == null
         && li.root == root.left && root.val > li.max
         
         ③ li == null && ri != null
         && ri.root == root.right && root.val < ri.min
         
         ④ li == null && ri == null
         */

        int leftBstSize = -1, rightBstSize = -1, max = root->val, min = root->val;
        
        if (li == nullptr) {
            leftBstSize = 0;
        } else if (li->root == root->left && root->val > li->max) {
            leftBstSize = li->size;
            min = li->min;
        }

        if (ri == nullptr) {
            rightBstSize = 0;
        } else if (ri->root == root->right && root->val < ri->min) {
            rightBstSize = ri->size;
            max = ri->max;
        }

        if (leftBstSize >= 0 && rightBstSize >= 0) {
            return new Info(root, 1 + leftBstSize + rightBstSize, max, min);
        }

        // 以root为根节点的二叉树并不是BST
        
        // 返回最大BST子树的节点数量较多的那个Info
        if (li != nullptr && ri != nullptr) return (li->size > ri->size) ? li : ri;
        
        // 返回li、ri中不为null的那个Info
        return (li != nullptr) ? li : ri;
    }
    
public:
    int largestBSTSubtree(TreeNode*root){
        return (root == nullptr) ? 0 : getInfo(root)->size;;
    }
};

行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.