📝个人主页:@Sherry的成长之路
🏠学习社区:Sherry的成长之路(个人社区)
📖专栏链接:练题
🎯长路漫漫浩浩,万事皆有期待
文章目录
最大二叉树
最大二叉树的解题思路和之前我们做的中后序构造二叉树解题思路差不多,不同的是这道题只给我们一个数组,让我们在数组中找出大数当节点,为什么说和构造二叉树那道题差不多呢?是因为我们在构造二叉树的时候的思路就是在数组中找到最大节点,然后分成左右部分,进入下一层递归,如此往复得到最大二叉树。
cpp
class Solution {
public:
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;
}
};
与上一道构造二叉树,不同之处是只有在一个数组里操作。
合并二叉树
合并二叉树是考察我们如何一次控制两个二叉树的题,题目思路并不难,就是将两个二叉树都有的节点将它们的值合并在一起组成新节点,如果只有一个有那么就将那一个直接拿过来就可以了,我们可以直接在第一个或者第二个树直接合并,相当于取长补短的思路,也可以创建一个新的树在上面合并两个二叉树,两种思路都可行且代码简单。
cpp
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if(root1==nullptr)
{
return root2;
}
if(root2==nullptr)
{
return root1;
}
root1->val+=root2->val;
root1->left=mergeTrees(root1->left,root2->left);
root1->right=mergeTrees(root1->right,root2->right);
return root1;
}
};
这里给出思路,即将合并好的二叉树放在第一棵树上并将其返回,但是题目用递归实现没那么容易的,第一次做的时候递归的结束判断条件想不出来。这里的递归结束就是判断如果第一棵树当前对应节点没有,那就返回第二个对应节点,如果第二个没有那就返回第一个,如果两个都没有那么返回的其中一个也就是null。
二叉搜索树中的搜索
二叉树的搜索是考察对于二叉搜索树的特性的使用,当然使用暴力搜索忽略其特性应该也能做得出来。
cpp
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;
}
};
这道递归里最重要的部分,仍然是要想通递归的结束条件判断,如果走到空了那就往上返回,该侧子树目前为空,再遍历另一侧如果仍然是空那就返回了空,如果在某一侧找到了节点,则向上返回当前的节点root
注意:如果找到了则会直接返回,当前是root2=找到的节点,第二个向右递归是进不去的直接返回了,这里也体现出了为什么我们最开始要创立一个root2它的目的就是接收返回值的,接收到返回值才能将节点所在处正确的返回。
其次是单层递归的逻辑,这里我们充分使用了二叉搜索树的特性,即二叉搜索树的左子树所有节点比根节点都要小,而且右子树比根节点数值都要大,利用这一特点,我们就可以有方向的进行搜索,判断当前节点与目标值val的大小比较。
验证二叉搜索树
验证二叉搜索树仍然是考察搜索树的特性,按照搜索树的特性来写代码,但是也有一些需要注意的点写在下方。
cpp
class Solution {
public:
long prev=LONG_MIN;
bool isValidBST(TreeNode* root) {
if(root==nullptr)
{
return true;
}
bool left=isValidBST(root->left);//左
//剪枝
if(left==false)
{
return false;
}
bool cur=false;//中
if(root->val>prev)
{
cur=true;
}
//剪枝
if(cur==false)
{
return false;
}
prev=root->val;
bool right=isValidBST(root->right);//右
return left&&right&&cur;
}
};
注意在里面创建两个布尔类型的用途,其次是第一句判断结束并不是可有可无的,没有一定会超时,它的作用是将两个布尔类型赋成true,它并不是像有些递归条件里的走到叶子节点返回上一层,那样的题可能由于逻辑代码中存在指针不为空才能进入递归的判断,显得可有可无,但本题它的用处并非这样。再者逻辑判断代码也很重要·,一开始可能会把代码写成判断该节点的数值比左节点大且比右节点小就直接判断是true,这是错误的,因为我们要判断的是比它的左子树小,右子树大,而不是单纯比较比某节点的大小,所以这道题的思路一定要选用中序遍历,使它能够直接从下面进行遍历,从下往上走就可以知道下面的子树符不符合搜索的规范了。整体来看坑很多需要注意。
二叉搜索树的大多数判断类型题,都可以采用中序遍历放到一个数组中然后去操作数组比较其中数据的大小来完成对应的题目判断。因为中序遍历是一个递增的序列。
总结:
今天我们完成了最大二叉树、合并二叉树、二叉搜索树中的搜索、验证二叉搜索树四道题,相关的思想需要多复习回顾。接下来,我们继续进行算法练习。希望我的文章和讲解能对大家的学习提供一些帮助。
当然,本文仍有许多不足之处,欢迎各位小伙伴们随时私信交流、批评指正!我们下期见~