总结
二叉搜索树本质是上有序数组,关键就在于有序
● 654.最大二叉树
● 617.合并二叉树
● 700.二叉搜索树中的搜索
● 98.验证二叉搜索树
● 654.最大二叉树
/*654. 最大二叉树
中等
给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:
创建一个根节点,其值为 nums 中的最大值。
递归地在最大值 左边 的 子数组前缀上 构建左子树。
递归地在最大值 右边 的 子数组后缀上 构建右子树。
返回 nums 构建的 最大二叉树 。
提示:
1 <= nums.length <= 1000
0 <= nums[i] <= 1000
nums 中的所有整数 互不相同
*/
class Solution_654 {
public:
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) {}
};
/* 输入参数为不重复的整数数组 nums,返回结果为根节点
终止条件为遍历数组剩一个元素,那需要保证传入参数不为空
单层递归逻辑:
寻找 nums最大值作为根节点,暴力比较
判断终止条件,若终止,返回根节点
通过该节点切割 nums
左子树遍历,输入为左数组,返回为左子节点
右子树遍历,输入为右数组,返回为右子节点
返回根节点*/
TreeNode *build(vector<int> &nums) {
//寻找 nums最大值作为根节点,暴力比较
int max_val = 0;
int max_val_index = 0;
int temp = 0;
for(auto i : nums){
if(i > max_val) {
max_val = i;
max_val_index = temp;
}
temp += 1;
}
TreeNode *root = new TreeNode(max_val);
//判断终止条件,若终止,返回根节点
if(nums.size() == 1)
return root;
//通过该节点切割 nums
vector<int> nums_left(nums.begin(), nums.begin() + max_val_index);
vector<int> nums_right(nums.begin() + max_val_index + 1, nums.end());
//左子树遍历,输入为左数组,返回为左子节点
if (nums_left.empty())
root->left = nullptr;
else
root->left = build(nums_left);
//右子树遍历,输入为右数组,返回为右子节点
if (nums_right.empty())
root->right = nullptr;
else
root->right = build(nums_right);
return root;
}
TreeNode *constructMaximumBinaryTree(vector<int> &nums) {
if(nums.empty()){
return nullptr;
}
return build(nums);
}
};
● 617.合并二叉树
/*617. 合并二叉树
简单
给你两棵二叉树: root1 和 root2 。
想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。
合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。
返回合并后的二叉树。
注意: 合并过程必须从两个树的根节点开始。*/
class Solution_617 {
public:
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) {}
};
/* 输入参数为俩个树的节点,返回值为新二叉树根节点
终止条件为两个节点均为空
单层递归逻辑:
判断终止条件,若为真则返回
更新新二叉树当前节点值,值为传入两节点值之和
遍历左子树
遍历右子树
返回根节点
优化方向,目前是新建了一个树,可以在原有的树上操作
*/
TreeNode *build(TreeNode *root1, TreeNode *root2) {
//终止条件为两个节点均为空
if (!root1 && !root2)
return nullptr;
//更新新二叉树当前节点值,值为传入两节点值之和
int val_1 = 0;
TreeNode *root1_left = nullptr;//可能该节点本身为空,访问其左右子树会出错
TreeNode *root1_right = nullptr;
if (root1) {
val_1 = root1->val;
root1_left = root1->left;
root1_right = root1->right;
}
int val_2 = 0;
TreeNode *root2_left = nullptr;
TreeNode *root2_right = nullptr;
if (root2) {
val_2 = root2->val;
root2_left = root2->left;
root2_right = root2->right;
}
TreeNode *root = new TreeNode(val_1 + val_2);
//遍历左子树
root->left = build(root1_left, root2_left);
//遍历右子树
root->right = build(root1_right, root2_right);
return root;
}
TreeNode *mergeTrees(TreeNode *root1, TreeNode *root2) {
return build(root1, root2);
}
};
● 700.二叉搜索树中的搜索
/*700. 二叉搜索树中的搜索
简单
给定二叉搜索树(BST)的根节点 root 和一个整数值 val。
你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null 。*/
class Solution_700 {
public:
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) {}
};
/*
* 中序遍历
输入参数为当前节点及目标值,返回值为找到的节点
终止逻辑为当前节点为空,返回空
单层递归逻辑:
判断终止条件,若为真返回空
判断当前节点值与目标值是否相等
若相等,直接返回该节点
若目标值大于当前节点值,遍历右子树
若小于,遍历左子树
返回得到的节点
*/
TreeNode *get(TreeNode *root, int &val){
//终止逻辑为当前节点为空,返回空
if(!root)
return nullptr;
//判断当前节点值与目标值是否相等
TreeNode *node = nullptr;
if(val == root->val)
return root;
else if(val > root->val)
node = get(root->right, val);
else if(val < root->val)
node = get(root->left, val);
return node;
}
TreeNode *searchBST(TreeNode *root, int val) {
return get(root, val);
}
};
● 98.验证二叉搜索树
/*
* 98. 验证二叉搜索树
中等
给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
节点的左子树只包含 小于 当前节点的数。
节点的右子树只包含 大于 当前节点的数。
所有左子树和右子树自身必须也是二叉搜索树。
*/
class Solution_98 {
public:
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) {}
};
/*
* 输入参数为当前节点,返回值为是否为有效二叉搜索树
终止条件为当前节点为空
单层递归逻辑:
判断终止条件,返回真
遍历左子树
判断当前节点值是否大于等于上一个节点值,即是否是递增的
若为真,返回假
遍历右子树
返回真
注意:应该是左子树所有节点小于中间节点,而不是左子节点小于中间节点
*/
TreeNode* pre;
bool get(TreeNode* node){
//判断终止条件,返回真
if(!node)
return true;
//遍历左子树
bool left = get(node->left);
//判断当前节点值是否大于等于上一个节点值,即是否是递增的
if(pre && pre->val >= node->val)
return false;
pre = node;
//遍历右子树
bool right = get(node->right);
return (left && right);
}
bool isValidBST(TreeNode* root) {
return get(root);
}
};