《代码随想录》刷题打卡day15:二叉树part05

文章目录

【654.最大二叉树】

思路:和已知后序和中序遍历构造二叉树类似,一个一个找根节点然后分隔数组,注意每次分隔不用定义新的数组,而是通过下标索引直接在原数组上操作

c++ 复制代码
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        TreeNode* node = new TreeNode(0);
        if (nums.size() == 1) {
            node->val = nums[0];
            return node;
        }
        // 找到数组中最大的值和对应的下标
        int maxValue = 0;
        int maxValueIndex = 0;
        for (int i = 0; i < nums.size(); i++) {
            if (nums[i] > maxValue) {
                maxValue = nums[i];
                maxValueIndex = i;
            }
        }
        node->val = maxValue;
        // 最大值所在的下标左区间 构造左子树
        if (maxValueIndex > 0) {
            vector<int> newVec(nums.begin(), nums.begin() + maxValueIndex);
            node->left = constructMaximumBinaryTree(newVec);
        }
        // 最大值所在的下标右区间 构造右子树
        if (maxValueIndex < (nums.size() - 1)) {
            vector<int> newVec(nums.begin() + maxValueIndex + 1, nums.end());
            node->right = constructMaximumBinaryTree(newVec);
        }
        return node;
    }
【617.合并二叉树】

递归法:前序遍历,每次传入两个结点进行操作,容易理解。

c++ 复制代码
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        if(root1 == nullptr) return root2;
        if(root2 == nullptr) return root1;
        TreeNode* node = new TreeNode(0);
        node->val = root1->val + root2->val;
        node->left = mergeTrees(root1->left, root2->left);
        node->right = mergeTrees(root1->right, root2->right);
        return node;
    }

迭代法:把两个树的节点同时加入队列进行比较,模拟层序遍历

c++ 复制代码
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
        if (t1 == NULL) return t2;
        if (t2 == NULL) return t1;
        queue<TreeNode*> que;
        que.push(t1);
        que.push(t2);
        while(!que.empty()) {
            TreeNode* node1 = que.front(); que.pop();
            TreeNode* node2 = que.front(); que.pop();
            // 此时两个节点一定不为空,val相加
            node1->val += node2->val;

            // 如果两棵树左节点都不为空,加入队列
            if (node1->left != NULL && node2->left != NULL) {
                que.push(node1->left);
                que.push(node2->left);
            }
            // 如果两棵树右节点都不为空,加入队列
            if (node1->right != NULL && node2->right != NULL) {
                que.push(node1->right);
                que.push(node2->right);
            }

            // 当t1的左节点为空 t2左节点不为空,就赋值过去
            if (node1->left == NULL && node2->left != NULL) {
                node1->left = node2->left;
            }
            // 当t1的右节点为空 t2右节点不为空,就赋值过去
            if (node1->right == NULL && node2->right != NULL) {
                node1->right = node2->right;
            }
        }
        return t1;
    }
【700.二叉搜索树中的搜索】

二叉搜索树 是一个有序树

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  • 它的左、右子树也分别为二叉搜索树

思路:都挺好想的,一下就懂。

递归法:

c++ 复制代码
TreeNode* searchBST(TreeNode* root, int val) {
        if(root == nullptr || root->val == val) return root;
        if(root->val > val){
            return searchBST(root->left, val);
        }
        if(root->val < val){
            return searchBST(root->right, val);
        }
        return nullptr;
    }

迭代法:

c++ 复制代码
TreeNode* searchBST(TreeNode* root, int val) {
        while(root != nullptr){
            if(root->val > val){
                root = root->left;
            }else if(root->val < val){
                root = root->right;
            }else return root;
        }
        return root;
    }
【98.验证二叉搜索树】

思路:中序遍历下,输出的二叉搜索树节点的数值是有序序列。

有了这个特性,验证二叉搜索树,就相当于变成了判断一个序列是不是递增的了。

递归法:

c++ 复制代码
vector<int> vec;
    void travelsal(TreeNode* root){
        if(root == nullptr) return;
        travelsal(root->left);
        vec.push_back(root->val);// 将二叉搜索树转换为有序数组
        travelsal(root->right);
    }
    bool isValidBST(TreeNode* root) {
        travelsal(root);
        for(int i = 1; i < vec.size(); i++){
            if(vec[i] <= vec[i-1]) return false;
        }
        return true;
    }

迭代法:模拟中序遍历,需要一个pre来记录前一个结点,还是有点绕,需要多思考熟悉。

c++ 复制代码
bool isValidBST(TreeNode* root) {
        stack<TreeNode*> st;
        TreeNode* cur = root;
        TreeNode* pre = nullptr;// 记录前一个结点
        while(!st.empty() || cur != nullptr){
            if(cur != nullptr){
                st.push(cur);
                cur = cur->left;// 左
            }else{
                cur = st.top();// 中
                st.pop();
                if(pre != nullptr && cur->val <= pre->val) return false;
                pre = cur;// 保存前一个访问的节点
                cur = cur->right;// 右
            }
        }
        return true;
    }

ps:我们要比较的是 左子树所有节点小于中间节点,右子树所有节点大于中间节点

不能只判断左节点小于其根节点,右结点大于其根节点

反例:

相关推荐
Kurisu_红莉栖2 小时前
力扣56合并区间
算法·leetcode
Darling噜啦啦2 小时前
二叉树与递归算法实战:从树结构到 LeetCode 爬楼梯,一文吃透前端数据结构与递归思维
前端·javascript·数据结构
Irissgwe2 小时前
算法的时间复杂度和空间复杂度
数据结构·c++·算法·c·时间复杂度·空间复杂度
随意起个昵称2 小时前
区间dp-基础题目3(永别)
c++·算法
周末也要写八哥2 小时前
有向图Hierholzer算法的另一种实现
算法
bIo7lyA8v2 小时前
算法调优中的性能回归与基准测试分析的技术8
算法·数据挖掘·回归
有点。2 小时前
C++贪心算法二(练习题)
c++·算法·贪心算法
西安邮电大学2 小时前
贪心算法详细讲解
java·后端·其他·算法·面试
开源Z2 小时前
LeetCode 135 · 分发糖果:两次扫描,先左后右取最大
算法·leetcode