二叉树篇--代码随想录算法训练营第十七天| 654.最大二叉树 , 617.合并二叉树 ,700.二叉搜索树中的搜索 , 98.验证二叉搜索树

654.最大二叉树

题目链接:. - 力扣(LeetCode)

视频讲解:又是构造二叉树,又有很多坑!| LeetCode:654.最大二叉树

题目描述:

给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:

  1. 创建一个根节点,其值为 nums 中的最大值。
  2. 递归地在最大值 左边 的 子数组前缀上 构建左子树。
  3. 递归地在最大值 右边 的 子数组后缀上 构建右子树。

返回 nums 构建的 最大二叉树 

示例 1:

输入:nums = [3,2,1,6,0,5]
输出:[6,3,5,null,2,0,null,null,1]

解题思路:

同昨天所完成的已知前序和中序/中序和后序构建二叉树题目思路一致:

二叉树篇--代码随想录算法训练营第十六天|513.找树左下角的值,112. 路径总和,113. 路径总和Ⅱ,106.从中序与后序遍历序列构造二叉树,105.从前序与中序遍历序列构造二叉树-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_67804957/article/details/140849666即每次确定最大元素位置,按其左右进行划分。

代码:

class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        if(nums.size() == 0) return nullptr;
        int maxIdx = 0;
        int maxVal = nums[0];
        for(int i = 1; i < nums.size(); i++)
        {
            if(nums[i] > maxVal)
            {
                maxVal = nums[i];
                maxIdx = i;
            }
        }
        TreeNode* root = new TreeNode(maxVal);
        vector<int> leftNums(nums.begin(),nums.begin()+maxIdx);
        vector<int> rightNums(nums.begin()+maxIdx+1,nums.end());

        root->left = constructMaximumBinaryTree(leftNums);
        root->right = constructMaximumBinaryTree(rightNums);

        return root;
    }
};

617.合并二叉树

题目链接:. - 力扣(LeetCode)

视频讲解:一起操作两个二叉树?有点懵!| LeetCode:617.合并二叉树

题目描述:

给你两棵二叉树: root1 和 root2 。

想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。

返回合并后的二叉树。

注意: 合并过程必须从两个树的根节点开始。

示例 1:

输入:root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7]
输出:[3,4,5,5,4,null,7]

解题思路:

目标是将修改结果添加到root1树。采用前序遍历,遍历中会存在三种情况:

  1. root1为空,root2不为空-->把当前root2节点拼接到root1节点上,即返回root2节点
  2. root1不为空,root2为空-->root1节点不改变,即返回root1节点
  3. root1和root2均不为空-->两节点值相加后保存至root1节点中,并返回root1节点

代码:

class Solution {
public:
    TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
        if(!root1) return root2;
        if(!root2) return root1;
        root1->val += root2->val;
        root1->left = mergeTrees(root1->left,root2->left);
        root1->right = mergeTrees(root1->right,root2->right);
        return root1;
    }
};

700.二叉搜索树中的搜索

题目链接:. - 力扣(LeetCode)

视频讲解:不愧是搜索树,这次搜索有方向了!| LeetCode:700.二叉搜索树中的搜索

题目描述:

给定二叉搜索树(BST)的根节点 root 和一个整数值 val

你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。

示例 1:

输入:root = [4,2,7,1,3], val = 2
输出:[2,1,3]

解题思路:

看到搜索树,首先要想到中序遍历,因为中序遍历可以将搜索树中元素递增排序

但此题只用到了中节点比左子树任意值大,比右子树任意值小特点。不需要遍历整棵树。

因此只需通过判断目标值与中心节点值大小来确定目标值的大体方位,有点像二分查找。

代码:

递归法

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->val < val) result = searchBST(root->right,val);
        return result;
    }
};

根据搜索树的性质开展的遍历法

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

遍历法(未用到搜索树性质)

class Solution {
public:
    TreeNode* searchBST(TreeNode* root, int val) {
        if(root == nullptr) return root;
        stack<TreeNode*> st;
        st.push(root);
        while(!st.empty())
        {
            TreeNode* node = st.top();
            st.pop();
            if(node->val == val) return node;
            if(node->left && node->val > val) st.push(node->left);
            if(node->right && node->val < val) st.push(node->right);
        }
        return nullptr;
    }
};

98.验证二叉搜索树

题目链接:. - 力扣(LeetCode)

视频讲解:你对二叉搜索树了解的还不够! | LeetCode:98.验证二叉搜索树

题目描述:

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

  • 节点的左

    子树

    只包含 小于 当前节点的数。
  • 节点的右子树只包含 大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

示例 1:

输入:root = [2,1,3]
输出:true

解题思路:

搜索树题目中通常首选中序遍历,因为这样可以确保遍历出的元素按单调递增的顺序排列。

1)双指针法

使用一个pre指针指向当前节点的前一个节点,两节点进行元素大小比较,若pre节点元素值较大,则判断为不是搜索树。

2)最大值法

定义一个maxVal变量,每次记录除当前节点外已遍历节点最大值,并与当前节点进行比较,若maxVal较大,则判断为不是搜索树。

代码:

首选--双指针法

class Solution {
public:
    TreeNode* pre = nullptr;
    bool isValidBST(TreeNode* root) {
        if(!root) return true;
        bool left = isValidBST(root->left);//左
        if(pre && pre->val >= root->val) return false; //中
        pre = root;                                    //中
        bool right = isValidBST(root->right);//右
        return left && right;
    }
};

最大值验证法

class Solution {
public:
    long long maxVal = LONG_MIN; // 因为后台测试数据中有int最小值
    bool isValidBST(TreeNode* root) {
        if (root == NULL) return true;

        bool left = isValidBST(root->left);
        // 中序遍历,验证遍历的元素是不是从小到大
        if (maxVal < root->val) maxVal = root->val;
        else return false;
        bool right = isValidBST(root->right);

        return left && right;
    }
};
 1)补充

NT_MIN:-2147483648
INT_MAX:2147483647
LONG_MIN:-2147483648
LONG_MAX:2147483647
LLONG_MIN:-9223372036854775808
LLONG_MAX:9223372036854775807

2)缺点

自定义maxVal初始值要随节点变量类型而变化,例如:若节点为long long类型,将maxVal初始值设置为INT_MIN,此时结果会出错。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值