代码随想录算法训练营第二十天| 654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树
参考《代码随想录》:https://programmercarl.com/0098.%E9%AA%8C%E8%AF%81%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91.html#%E7%AE%97%E6%B3%95%E5%85%AC%E5%BC%80%E8%AF%BE
参考acwing: http://www.acwing.com
654.最大二叉树
我是一看就会,一写就废。先看代码:
class Solution {
public:
unordered_map<int,int> pos;
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
for(int i = 0;i < nums.size();i++) pos[nums[i]] = i;
return build(nums,0,nums.size() - 1);
}
TreeNode* build(vector<int>& nums,int ln,int rn)
{
if(ln > rn) return NULL;
int max_value = -1;
for(int i = ln;i < rn + 1;i++)
{
if(nums[i] > max_value) max_value = nums[i];
}
int k = pos[max_value];
TreeNode* root = new TreeNode(max_value);
root->left = build(nums,ln, k - 1);
root->right = build(nums,k + 1,rn);
return root;
}
};
这道题目感觉让我学会很多,其实主体思路和前面的根据中序遍历和后序遍历构造二叉树是一样的,大家可以看我昨天的笔记,但是我有发现新的一写细节。首先是求最大值:
开始遇见找出最大值有点懵,不怕大家笑话,作为一个学习计算机6年的学生,从大学到研究生,找出最大值这个应该深入骨子里的东西居然能忘,我也是服了我自己了。不过也算是长记性了,当然这里我总结两个照最大值的方法:
1.使用max_element()方法,不过参数是nums.begin()和nums.end()迭代器,对于数组区间不会变化的可以,但是本题目不行,因为数组区间一直是减半,再从左子树和右子树入手,故此方法不能用。
2.就是使用for()循环的传统方法,使用一个max_value来记录,可以适应变化的区间。我第一次写的时候注意了,二刷就没注意。
然后是判断:
if(ln > rn) return NULL;
不管是第一次写的时候还是二刷的时候,我都忽略的一点就是这句话,没有这句话A不过去。这也是递归退出的条件,当时还觉得是老规矩,判断头节点,这次不是了。
617.合并二叉树
先看代码:
class Solution {
public:
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
if(t2) swap(t1,t2);
if(!t1) return NULL;
if(t2) t1->val += t2->val;
if(t2) t1->left = mergeTrees(t1->left,t2->left);
else t1->left = mergeTrees(t1->left,NULL);
if(t2) t1->right = mergeTrees(t1->right,t2->right);
else t1->right = mergeTrees(t1->right,NULL);
return t1;
}
};
这道题目,我看的y总的思路,直接讲代码吧,首先用swap()交换两个树两个指针交换,就是看看t2是不是空的,如果是空的,就不用往下进行了然后我们将t2合并到t1上,如果t2不为空,就进行递归合并,如果t2为空就合并NULL,左右子树同理。
700.二叉搜索树中的搜索
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
if(!root) return NULL;
if (root->val == val) return root;
else if(root->val > val) return searchBST(root->left,val);
else if(root->val < val) return searchBST(root->right,val);
else return NULL;
}
};
这道题目首先要明白什么是二叉搜索树,二叉搜索树的特性,然后写的时候估计有人和我一样,上来判断根,然后判断值,最后左右子树一递归。这样是错的,错在哪里,就是没注意二叉搜索树的特性,比根小的都在根的左边,比根大的都在根的右边,所以只要比较一边。
98.验证二叉搜索树
先看代码:
class Solution {
public:
vector<int> tree;
void inorder(TreeNode* root)
{
if(!root) return;
inorder(root->left);
tree.push_back(root->val);
inorder(root->right);
}
bool isValidBST(TreeNode* root) {
if(!root) return false;
inorder(root);
for(int i = 1;i < tree.size();i++)
{
if(tree[i] <= tree[i-1]) return false;
}
return true;
}
};
这道题目有很好的两个思路,首先是代码随想录的思路,就是将树中序转换为数组,这样个数组是单调递增的,只要里面有一个不是递增的就返回false。
第二个思路也很巧妙,我看到y总的思路,代码没写。思路就是既然根的左边都小于根,根的右边都大于根,那只要保证根的左子树的最大值都小于根,根的右子树的最小值都大于根即可。