代码随想录算法训练营day17 | 654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树

654.最大二叉树

点击查看代码
class Solution {
public:
    //找到[left, right)子树内的根节点,并与其左子树和右子树进行连接,最后返回子树的根节点
    TreeNode *searchRoot(vector<int> &nums, int left, int right) {
        if(left == right) return nullptr;
        int maxNum, maxIndex;
        //注意此处i < right而不是i < nums.size(),因为要处理的是传入的子树,而不是整棵树
        for(int i = left; i < right; ++i) {
            if(i == left) {
                maxNum = nums[left];
                maxIndex = left;
            }
            if(nums[i] > maxNum) {
                maxNum = nums[i];
                maxIndex = i;
            }
        }
        TreeNode *root = new TreeNode(maxNum);
        if(right - left == 1) return root;  //递归终止条件二:叶子节点直接返回,无需再递归构造子树
        int leftBegin = left, leftEnd = maxIndex;
        int rightBegin = maxIndex + 1, rightEnd = right;
        root->left = searchRoot(nums, leftBegin, leftEnd);
        root->right = searchRoot(nums, rightBegin, rightEnd);
        return root;
    }
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        return searchRoot(nums, 0, nums.size());
    }
};

与中序+前/后序构造二叉树的思路基本一致
根节点自顶向下找,边自底向上连接

什么时候递归函数前面加if,什么时候不加if:
一般情况来说:如果让空节点(空指针)进入递归,就不加if,如果不让空节点进入递归,就加if限制一下, 终止条件也会相应的调整(或无需终止条件)。

617.合并二叉树
解法一:自创解法

点击查看代码
class Solution {
public:
    void preOrder(TreeNode* root1, TreeNode* root1_parent, TreeNode* root2, TreeNode* root2_parent) {
        //递归终止条件1:
        if(root1 == nullptr && root2 == nullptr) return;
        //递归终止条件2
        if(root1 != nullptr && root2 == nullptr) return;
        //递归终止条件3
        if(root1 == nullptr && root2 != nullptr) {
            if(root2 == root2_parent->left) root1_parent->left = root2;
            if(root2 == root2_parent->right) root1_parent->right = root2;
            return;
        }
        
        if(root1 != nullptr && root2 != nullptr) {
            //根
            root1->val += root2->val;
            //左
            preOrder(root1->left, root1, root2->left, root2);
            //右
            preOrder(root1->right, root1, root2->right, root2);
        }
    }
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        //由于整颗树的父节点为空,root1 == nullptr && root2 != nullptr时进行递归会导致操作空指针,故提前剪枝
        if(root1 == nullptr) return root2;
        preOrder(root1, nullptr, root2, nullptr);
        return root1;
    }
};

解法二:代码随想录解法,值得学习

点击查看代码
class Solution {
public:
    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        if (t1 == NULL) return t2; // 如果t1为空,合并之后就应该是t2
        if (t2 == NULL) return t1; // 如果t2为空,合并之后就应该是t1
        // 修改了t1的数值和结构
        t1->val += t2->val;                             // 中
        t1->left = mergeTrees(t1->left, t2->left);      // 左
        t1->right = mergeTrees(t1->right, t2->right);   // 右
        return t1;
    }
};

700.二叉搜索树中的搜索

点击查看代码
class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        if(root == nullptr) return nullptr;
        else if(root->val == val) return root;
        else if(root->val < val) return searchBST(root->right, val);
        else return searchBST(root->left, val);
    }
};

二叉搜索树/二叉排序树的特点为左 < 中 < 右,找到空节点/失败节点即空指针时即查找失败,返回nullptr
递归时,要根据root->val与val的大小关系选择左或右(只选择一个方向)进行递归查找,而不是对整棵树进行递归遍历

98.验证二叉搜索树

点击查看代码
class Solution {
public:
    int maxNum;
    bool result = true;
    bool firstEle = true;
    void inorder(TreeNode* root) {
        if(root == nullptr) return;
        inorder(root->left);
        //第一个元素需要作为初始最大值,此条件非常关键,不加的话会导致很多特殊用例无法通过,
        //如首元素为INT_MIN,而maxNum若也初始化为INT_MIN,会导致result直接变为false,如[INT_MIN,1],int maxNum = INT_MIN时
        if(firstEle == true || root->val > maxNum) {
            maxNum = root->val;
            firstEle = false;
        }
        else result = false;
        inorder(root->right);
    }
    bool isValidBST(TreeNode* root) {
        inorder(root);
        return result;
    }
};

2025/03/01

posted @ 2025-03-01 14:15  coder小杰  阅读(15)  评论(0)    收藏  举报