打卡代码随想录第17天:LeetCode654.最大二叉树 、 617.合并二叉树、 700.二叉搜索树中的搜索、98.验证二叉搜索树

学习资料:代码随想录

文中含LLM生成内容,不一定对

654.最大二叉树

力扣题目地址

思路:不断寻找该部分的最大值去切割数组,不断递归,到在左闭右开区间不成立时,返回空节点。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* traversal(vector& nums,int leftIndex,int rightIndex){
        if(rightIndex<=leftIndex) return nullptr;     //左闭右开区间

        int maxValueIndex=leftIndex;
        for(int i=leftIndex+1;inums[maxValueIndex]){
                maxValueIndex=i;
            }
        }

        TreeNode* root = new TreeNode(nums[maxValueIndex]);

        root->left = traversal(nums,leftIndex,maxValueIndex);           //操作原数组,区间不要写错了。
        root->right = traversal(nums,maxValueIndex+1,rightIndex);
        
        return root;
    }
    TreeNode* constructMaximumBinaryTree(vector& nums) {       
        return traversal(nums,0,nums.size());                    //起手就是左闭右开
    }
};

617.合并二叉树

力扣题目链接

思路:把树都并到第一颗,递归法,tree1遍历到空,就返回到tree2;tree2遍历到空,就返回到tree1;

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        if (t1 == NULL) return t2; 
        if (t2 == NULL) return t1; 
        t1->val += t2->val;                             // 中
        t1->left = mergeTrees(t1->left, t2->left);      // 左,通过=赋值,

        t1->right = mergeTrees(t1->right, t2->right);   // 右
        return t1;
    }
};

迭代法:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        if(root1==nullptr) return root2;
        if(root2==nullptr) return root1;
        queue que;
        que.push(root1);
        que.push(root2);
        while(!que.empty()){                           //不需要层相关的数据了,就不加for了
            TreeNode* node1=que.front();  que.pop();
            TreeNode* node2=que.front();  que.pop();

            node1->val+=node2->val;
//共有五种情况,三种需要处理,两种不需要处理
            if(node1->left&&node2->left){
                que.push(node1->left);
                que.push(node2->left);
            }
            if(node1->right&&node2->right){
                que.push(node1->right);
                que.push(node2->right);
            }
            if(!node1->left&&node2->left){
                node1->left=node2->left;   //不用push了,直接往里放.如果 t1->left 不为空,而 t2->left 为空,则根本不需要处理。原因是 t1 已经有左子节点(t1->left != NULL),并且 t2 没有需要合并的左子节点(t2->left == NULL),无需任何操作,t1->left 保持不变即可。

            }
            if(!node1->right&&node2->right){
                node1->right=node2->right;
            }
        }

        return root1;
    }
};

700.二叉搜索树中的搜索

力扣题目地址

思路:搜索树是有序的,按排序搜索,递归:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        if(root==nullptr||root->val==val) return root;
        TreeNode* result = nullptr;
        if(root->val>val) {                      //充分利用搜索树性质
            result=searchBST(root->left,val);
        }
        if(root->valright,val);
        }
        return result;
    }
};

迭代:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        while(root!=nullptr){
            if(root->val>val)  root=root->left;
            else if(root->valright;
            else{return root;}
        }
        return nullptr;
    }
};

98.验证二叉搜索树

力扣题目链接

思路1:遍历转换成数组,然后验证是否有序

class Solution {
private:
    vector vec;
    void traversal(TreeNode* root) {
        if (root == NULL) return;
        traversal(root->left);
        vec.push_back(root->val); // 将二叉搜索树转换为有序数组
        traversal(root->right);
    }
public:
    bool isValidBST(TreeNode* root) {
        vec.clear(); // 不加这句在leetcode上也可以过,但最好加上
        traversal(root);
        for (int i = 1; i < vec.size(); i++) {
            // 注意要小于等于,搜索树里不能有相同元素
            if (vec[i] <= vec[i - 1]) return false;
        }
        return true;
    }
};

思路2:递归,实时更新最大值,因为搜索树不是简单的一个节点处左中右越来越大就行,这里有双指针的样子了

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    long long maxValue=LONG_MIN;      //要用中序遍历,数会越来越大,所以定义一个最大值;因为测试集中有int最小值,所以用LONG_MIN

    bool isValidBST(TreeNode* node) {
        if(node==nullptr) return true;
        bool left=isValidBST(node->left);
        if(node->val>maxValue) maxValue=node->val;
        else {return false;}
        bool right=isValidBST(node->right);
        return left&&right;
    }
};

思路:双指针法:将前一个值记录下来与本值比较

class Solution {
public:
    TreeNode* pre = NULL; // 用来记录前一个节点
    bool isValidBST(TreeNode* root) {
        if (root == NULL) return true;
        bool left = isValidBST(root->left);

        if (pre != NULL && pre->val >= root->val) return false;  //如果根节点返回false的话,往上也没有要返回的了,不论left和right也就返回false了
        pre = root; // 记录前一个节点

        bool right = isValidBST(root->right);
        return left && right;
    }
};

但是语法上true和false不是同一级别的吗,为什么你这里看起来false比true优先级要高,遇到false就都不管了?

你提到的问题其实是关于 短路求值(short-circuit evaluation) 和 递归的早期返回 的。

短路求值(short-circuit evaluation)

在 C++ 中,&&(逻辑与)运算符是使用短路求值的。当我们写 A && B 时:

  • 如果 Afalse,则 B 不会被求值,因为无论 B 是什么,整个表达式都会是 false
  • 如果 Atrue,那么会继续计算 B

这种行为应用于你代码中的 return left && right;。具体来说:

  • 如果 leftfalse,那么 right 不会被求值,直接返回 false
  • 如果 lefttrue,那么才会判断 right,然后返回最终结果。

在递归中如何工作?

在你的代码中,递归的返回值在 leftright 上起到了决定性的作用:

  • 当递归进入某个节点时,会先检查左子树(left),然后判断当前节点值与 pre 的值。如果违反了条件,就会返回 false,并且不会再继续检查右子树,因为我们已经知道这部分不合法。
  • 如果左子树(left)是 false,那么根据短路求值的规则,right 就不会被求值,直接返回 false
  • 如果左子树(left)是 true,那么才会递归右子树(right),并返回 left && right 的结果。

关键点

  • 逻辑与(&&)的短路求值:一旦 leftfalse,整个表达式的值就会是 false,不再计算 right
  • 早期返回(return false:如果在递归过程中发现不符合二叉搜索树规则,立即返回 false 并结束当前递归。

因此,leftright 的返回值并不意味着 优先级。实际上,false 不会影响到 true 的判断,关键是 一旦某一部分不符合要求,后续部分就无需计算

思路3:双指针

你可能感兴趣的:(算法,数据结构)