654.最大二叉树
这道题和通过中序和后序序列构建二叉树的思路异曲同工,递归三步走:
1. 参数:返回TreeNode指针,传入参数,数组以及开始和结束索引;
2. 结束条件:如果数组为空,返回nullptr;如果数组只剩一个元素,说明到了叶子节点,返回即可;
3. 单层处理逻辑:(前序遍历) 首先找最大值,然后把最大值构建为根节点,根节点的左右节点再递归即可。
详细代码:
class Solution {
public:
TreeNode* dfs(vector<int>& nums, int l, int r)
{
//结束条件
if(l>=r) return nullptr;
if(r-l==1)
{
TreeNode* root = new TreeNode(nums[l]);
return root;
}
//找最大值
int max_index;
int max_value = INT_MIN;
for(int i=l;i<r;i++)
{
if(nums[i]>max_value)
{
max_value = nums[i];
max_index = i;
}
}
//分割-左闭右开
TreeNode* root = new TreeNode(max_value);
int l_beg = l;
int l_end = max_index;
int r_beg = max_index+1;
int r_end = r;
//递归
root->left = dfs(nums, l_beg, l_end);
root->right = dfs(nums,r_beg, r_end);
return root;
}
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
//if(nums.size()==0) return nullptr;
return dfs(nums,0,nums.size());
}
};
617.合并二叉树
这道题使用前序遍历,中左右即可,我写的错误代码如下:
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if(root1==nullptr&&root2==nullptr) return nullptr;
//中
TreeNode* root = new TreeNode(0);
if(root1==nullptr) root->val = root2->val;
else if(root2==nullptr) root->val = root1->val;
else{
root->val =root1->val+root2->val;
root->left = mergeTrees(root1->left, root2->left);
root->right = mergeTrees(root1->right, root2->right);
return root;
}
}
};
debug发现这种思路的错误之处在于,当其中一个节点为空时,这个时候只是把另一个root的值给了新的节点,但是另一个root的子节点并不会随之复制,这样会导致新树的节点缺失,正确的思路应该是返回另一个root的指针,而不是单纯的值复制,修改后可以运行的代码如下:
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if(root1==nullptr&&root2==nullptr) return nullptr;
//中
TreeNode* root = new TreeNode(0);
if(root1==nullptr) //root->val = root2->val;
return root2;
else if(root2==nullptr) //root->val = root1->val;
return root1;
else{
root->val =root1->val+root2->val;
root->left = mergeTrees(root1->left, root2->left);
root->right = mergeTrees(root1->right, root2->right);
return root;
}
}
};
但是这个代码不简洁易懂,看了代码随想录之后精炼代码如下:
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if(root1==nullptr) return root2;
if(root2==nullptr) return root1;
TreeNode* root = new TreeNode(0);
root->val =root1->val+root2->val;//中
root->left = mergeTrees(root1->left, root2->left); //左
root->right = mergeTrees(root1->right, root2->right); //右
return root;
}
};
700.二叉搜索树中的搜索
这道题考察的是二叉搜索树的性质,二叉搜索树中左子树所有元素小于根节点小于右子树,同时左右子树也满足上述,本质上来说,如果把二叉搜索树的中序遍历打印出来,就是一个递增的序列。因此这道题,直接使用该性质作答,代码如下:
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
if(root==nullptr) return nullptr;
TreeNode* cur = root;
while(cur!=nullptr)
{
if(cur->val==val) break;
else if(cur->val>val) cur=cur->left;
else cur = cur->right;
}
return cur;
}
};
学习代码随想录的递归写法:
1. 确定递归函数的参数和返回值
递归函数的参数传入的就是根节点和要搜索的数值,返回的就是以这个搜索数值所在的节点。
2. 确定终止条件
如果root为空,或者找到这个数值了,就返回root节点。
3. 确定单层递归的逻辑
看看二叉搜索树的单层递归逻辑有何不同。
因为二叉搜索树的节点是有序的,所以可以有方向的去搜索。
如果root->val > val,搜索左子树,如果root->val < val,就搜索右子树,最后如果都没有搜索到,就返回NULL。
详细代码如下:
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
if(root==nullptr|| root->val==val) return root;
if(root->val>val) return searchBST(root->left, val);
if(root->val<val) return searchBST(root->right, val);
return nullptr; //都没找到,返回nullptr
}
};
98.验证二叉搜索树
递归写法:需要维护一个pre指针来代表中序遍历的前一个节点,两者比较大小,用中序遍历来完成这道题,详细代码如下:
class Solution {
public:
TreeNode* pre = nullptr;
bool isValidBST(TreeNode* root) {
if(root==nullptr) return true;
bool left = isValidBST(root->left);
//中
if(pre!=nullptr&&pre->val>=root->val) return false;
pre = root; //更新前一节点
bool right = isValidBST(root->right);
return left&&right;
}
};
迭代写法:模拟过程
详细代码如下:
class Solution {
public:
bool isValidBST(TreeNode* root) {
//迭代写法
TreeNode* pre = nullptr;
TreeNode* cur = root;
stack<TreeNode*> s;
while(cur!=nullptr||!s.empty())
{
if(cur)
{
s.push(cur);
cur=cur->left;
}
else
{
cur = s.top();
s.pop();
if(pre!=nullptr&&pre->val>=cur->val) return false; //比较
pre = cur; //更新pre
cur = cur->right;
}
}
return true;
}
};