leetcode654:最大二叉树
文章讲解:leetcode654
leetcode617:合并二叉树
文章讲解:leetcode617
leetcode700:二叉搜索树中的搜索
文章讲解:leetcode700
leetcode98:验证二叉搜索树
文章讲解:leetcode98
目录
1,leetcode654 最大二叉树
有了昨天的铺垫,这道题还是不难的。在最大处切就行。
class Solution {
public:
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
TreeNode* root ;
if(nums.size()<=0)return nullptr;
if (nums.size()==1){
return new TreeNode(nums[0]);
}
int max = INT_MIN;
int maxIndex = -1;
for(int i = 0;i<nums.size();i++){
if(nums[i]>max){
max = nums[i];
maxIndex = i;
}
}
root = new TreeNode(max);
if(maxIndex>0){
vector<int>left(nums.begin(), nums.begin()+maxIndex);
root->left = constructMaximumBinaryTree(left);
}
if(maxIndex<nums.size()-1){
vector<int>right(nums.begin()+maxIndex+1, nums.end());
root->right = constructMaximumBinaryTree(right);
}
return root;
}
};
卡了一下的地方在于构建right和left的区间,传入两个索引位置应该是左闭右开,left的结尾传入的是maxIndex,而不是maxIndex-1。
class Solution {
private:
// 在左闭右开区间[left, right),构造二叉树
TreeNode* traversal(vector<int>& nums, int left, int right) {
if (left >= right) return nullptr;
// 分割点下标:maxValueIndex
int maxValueIndex = left;
for (int i = left + 1; i < right; ++i) {
if (nums[i] > nums[maxValueIndex]) maxValueIndex = i;
}
TreeNode* root = new TreeNode(nums[maxValueIndex]);
// 左闭右开:[left, maxValueIndex)
root->left = traversal(nums, left, maxValueIndex);
// 左闭右开:[maxValueIndex + 1, right)
root->right = traversal(nums, maxValueIndex + 1, right);
return root;
}
public:
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
return traversal(nums, 0, nums.size());
}
};
代码随想录的这个代码就避免了每次递归创建两个vector的消耗。
2,leetcode617 合并二叉树
这道题是操作两棵树,意味着在遍历过程中两棵树要同步。题目中有一点需要注意,就是如果一个是null,另一个不是,就返回那个不是的。因此其实真正需要遍历的是两个数的公共部分,不公共的部分只需要返回不是空的那颗子树即可:
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if(root1 == nullptr)return root2;
if(root2 == nullptr)return root1;
root1->val = root1->val + root2->val;
root1->left = mergeTrees(root1->left,root2->left);
root1->right = mergeTrees(root1->right,root2->right);
return root1;
}
};
拿下。
3,leetcode700 二叉搜索树中的搜索。
数据结构的常规操作了:
递归:
class Solution {
public:
TreeNode* result;
TreeNode* searchBST(TreeNode* root, int val) {
if(root == nullptr)return nullptr;
else if(root->val == val)return root;
else if(root->val > val){
result = searchBST(root->left,val);
}else if(root->val<val){
result = searchBST(root->right, val);
}
return result;
}
};
迭代:
public:
TreeNode* result;
TreeNode* searchBST(TreeNode* root, int val) {
if(root == nullptr)return nullptr;
else if(root->val == val)return root;
while(root!=nullptr){
if(root->val > val){
root = root->left;
}else if(root->val < val){
root = root->right;
}
else if(root->val == val){
return root;
}
}
return nullptr;
}
};
bst节点的遍历很有规律,因此很简单。
4,leetcode98 验证二叉搜索树
- 节点的左子树只包含 小于 当前节点的数。
- 节点的右子树只包含 大于 当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
这道题的定义完全就是递归定义,因此递归判断一下即可。
class Solution {
public:
bool isValidBST(TreeNode* root) {
if(root == nullptr) return true;
if(root->left&&root->left->val>=root->val||root->right&&root->right->val<=root->val)return false;
return isValidBST(root->left)&&isValidBST(root->right);
}
};//卡了一个测试用例
在70多的时候卡住了。
- 陷阱1
不能单纯的比较左节点小于中间节点,右节点大于中间节点就完事了。
确实,应该是左边全部小于中间,右边全部大于中间才行。
class Solution {
public:
vector<int> nums;
void traverse(TreeNode* node){
if(node == nullptr)return;
traverse(node->left);
nums.push_back(node->val);
traverse(node->right);
}
bool isValidBST(TreeNode* root) {
traverse(root);
for(int i = 0;i<nums.size()-1;i++){
if(nums[i]>=nums[i+1])return false;
}
return true;
}
};
转化成中序遍历,再检查是否有序,就可以了。
5,总结
经过几天二叉树刷题,感觉渐入佳境,递归写的越来越熟练了。以前不敢写的现在也敢写了。在训练营中的坚持确实是有用的。