第六章 二叉树 part06
1.LeetCode.最大二叉树
1.1题目链接:654.最大二叉树
1.2思路:采用划分数组区间的方式进行构建最大二叉树,每次先找到数组区间的最大值作为根节点
1.3附加代码如下所示:
//法1
class Solution {
public:
TreeNode*constru(vector <int>&nums)
{
if(nums.size()==1)return new TreeNode(nums[0]);
int index=0;
int maxvalue=0;
for(int i=0;i<nums.size();i++)//中
{
if(nums[i]>maxvalue)
{
maxvalue=nums[i];
index=i;
}
}
TreeNode*node=new TreeNode(maxvalue);
if(index>0)//左
{
vector<int>leftvec(nums.begin(),nums.begin()+index);
node->left=constru(leftvec);
}
if(index<nums.size()-1)//右
{
vector<int>rightvec(nums.begin()+index+1,nums.end());
node->right=constru(rightvec);
}
return node;
}
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
return constru(nums);
}
};
//法2
class Solution {
public:
TreeNode*constru(vector <int>&nums,int left,int right)
{
if(left>=right)return nullptr;
int index=left;
int maxvalue=0;
for(int i=left;i<right;i++)//中
{
if(nums[i]>maxvalue)
{
maxvalue=nums[i];
index=i;
}
}
TreeNode*node=new TreeNode(maxvalue);
node->left=constru(nums,left,index);
node->right=constru(nums,index+1,right);
return node;
}
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
return constru(nums,0,nums.size());
}
};
2.LeetCode. 合并二叉树
2.1题目链接:617.合并二叉树
文章讲解:[代码随想录](https://programmercarl.com/0617.%E5%90%88%E5%B9%B6%E4%BA%8C%E5%8F%89%E6%A0%91.html)
视频讲解:B站卡哥视频
2.2思路:因为是传入了两个树,那么就有两个树遍历的节点t1 和 t2,如果t1 == NULL 了,两个树合并就应该是 t2 了(如果t2也为NULL也无所谓,合并之后就是NULL)。反过来如果t2 == NULL,那么两个数合并就是t1(如果t1也为NULL也无所谓,合并之后就是NULL)。
2.3附加代码如下所示:
//迭代法
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
queue<TreeNode*>que1;
queue<TreeNode*>que2;
if(root1==NULL&&root2!=NULL)return root2;
if(root1!=NULL&&root2==NULL)return root1;
if(root1==NULL&&root2==NULL)return NULL;
else
{
que1.push(root1);
que2.push(root2);
}
while(!que1.empty())
{
TreeNode* node1 = que1.front(); que1.pop();
TreeNode* node2 = que2.front(); que2.pop();
node1->val+=node2->val;
// 如果两棵树左节点都不为空,加入队列
if(node1->left!=NULL&&node2->left!=NULL)
{
que1.push(node1->left);
que2.push(node2->left);
}
// 如果两棵树右节点都不为空,加入队列
if(node1->right!=NULL&&node2->right!=NULL)
{
que1.push(node1->right);
que2.push(node2->right);
}
// 当t1的左节点 为空 t2左节点不为空,就赋值过去
if(node1->left==NULL&&node2->left!=NULL)
{
node1->left=node2->left;
}
// 当t1的右节点 为空 t2右节点不为空,就赋值过去
if(node1->right==NULL&&node2->right!=NULL)
{
node1->right=node2->right;
}
}
return root1;
}
};
//上述代码简化版 迭代法
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
queue<TreeNode*>que;
if(root1==NULL)return root2;
if(root2==NULL)return root1;
else
{
que.push(root1);
que.push(root2);
}
while(!que.empty())
{
TreeNode* node1 = que.front(); que.pop();
TreeNode* node2 = que.front(); que.pop();
node1->val+=node2->val;
// 如果两棵树左节点都不为空,加入队列
if(node1->left!=NULL&&node2->left!=NULL)
{
que.push(node1->left);
que.push(node2->left);
}
// 如果两棵树右节点都不为空,加入队列
if(node1->right!=NULL&&node2->right!=NULL)
{
que.push(node1->right);
que.push(node2->right);
}
// 当t1的左节点 为空 t2左节点不为空,就赋值过去
if(node1->left==NULL&&node2->left!=NULL)
{
node1->left=node2->left;
}
// 当t1的右节点 为空 t2右节点不为空,就赋值过去
if(node1->right==NULL&&node2->right!=NULL)
{
node1->right=node2->right;
}
}
return root1;
}
};
//递归法 前序遍历
class Solution {
public:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
//终止条件
if(root1==NULL)return root2;
if(root2==NULL)return root1;
root1->val+=root2->val;//中
//左
root1->left=mergeTrees(root1->left,root2->left);
//右
root1->right=mergeTrees(root1->right,root2->right);
return root1;
}
};
3.LeetCode.二叉搜索树中的搜索
3.1题目链接:700.二叉搜索树中的搜索
3.2思路:二叉搜索树是一个有序树:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉搜索树这就决定了,二叉搜索树,递归遍历和迭代遍历和普通二叉树都不一样。本题,其实就是在二叉搜索树中搜索一个节点。
3.3附加代码如下所示:
//迭代法 为利用到二叉搜索树
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
queue<TreeNode*>que;
if(root!=NULL)que.push(root);
else return NULL;
while(!que.empty())
{
int size=que.size();
for(int i=0;i<size;i++)
{
TreeNode*node=que.front();que.pop();
if(node->val==val)
{
return node;
}
else
{
if(node->left)que.push(node->left);
if(node->right)que.push(node->right);
}
}
}
return NULL;
}
};
//利用二叉搜索树 迭代法
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
while(root)
{
if(root->val>val)root=root->left;//小于给定值就是向左子树遍历
else if(root->val<val)root=root->right;//大于给定值就向右子树遍历
else return root;
}
return NULL;
}
};
//递归法 前序遍历
class Solution {
public:
TreeNode* searchBST(TreeNode* root, int val) {
if(root==NULL)return NULL;
if(root->val==val)return root;
if(root->val>val)
{
return searchBST(root->left,val);
}
else if(root->val<val)
{
return searchBST(root->right,val);
}
return NULL;
}
};
4.LeetCode.验证二叉搜索树
4.1题目链接:98.验证二叉搜索树
4.2思路:不能单纯的比较左节点小于中间节点,右节点大于中间节点就完事了,我们要比较的是 左子树所有节点小于中间节点,右子树所有节点大于中间节点。所以以上代码的判断逻
4.3附加代码如下所示:
//递归法 将二叉搜索树转化为有序数组检验该数组是否是有序的
class Solution {
public:
vector<int>result;
void traversal(TreeNode*node)
{
if(node==NULL)return;
traversal(node->left);//左
// 将二叉搜索树转换为有序数组
result.push_back(node->val);//中
traversal(node->right);//右
}
bool isValidBST(TreeNode* root) {
result.clear();//清楚之前遍历过的结果
traversal(root);
for(int i=0;i<result.size()-1;i++)//注意数组越界的问题
{
if(result[i+1]<=result[i])return false;// 注意要小于等于,搜索树里不能有相同元素
}
return true;
}
};
//常规递归法
class Solution {
public:
long long maxval=LONG_MIN;
bool isValidBST(TreeNode* root) {
if(root==NULL)return true;
bool left=isValidBST(root->left);//左
if(maxval<root->val)maxval=root->val;//中
else return false;
bool right=isValidBST(root->right);//右
return left&&right;
}
};
//上述代码稍微处理后的 建议避免初始化最小值,如下方法取到最左面节点的数值来比较。
class Solution {
public:
TreeNode* pre = NULL; // 用来记录前一个节点
bool isValidBST(TreeNode* root) {
if (root == NULL) return true;
bool left = isValidBST(root->left);
if (pre != NULL && pre->val >= root->val) return false;
pre = root; // 记录前一个节点
bool right = isValidBST(root->right);
return left && right;
}
};