二叉树的修改与构造
Leetcode.105.从前序与中序遍历序列构造二叉树
105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode) (leetcode-cn.com)
给定一棵树的前序遍历 preorder
与中序遍历 inorder
。请构造二叉树并返回其根节点。
Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
Output: [3,9,20,null,null,15,7]
思路:这道题的思路为分割数组。我们发现前序遍历中数组的第一个值为根节点。在中序数组中找到这个值,将他们分为左中序数组,右中序数组,再对前序的数组也进行分割。知道分割到叶子节点便返回
class Solution {
public:
TreeNode* trval(vector<int>&preorder,int preorderbegin,int preorderend,vector<int>&inorder,int inorderbegin,int inorderend){
//中序数组为空,返回空
if(preorderend-preorderbegin==0)return NULL;
//获取根节点的值,并构造一个根节点
int rootvalue=preorder[preorderbegin];
TreeNode* root=new TreeNode(rootvalue);
//如果这个数组中只有一个节点那么,这个节点就是叶子节点,并返回
if(preorderend-preorderbegin==1)return root;
//在中序数组中找到分割点,并将其分割
int qgpointval=inorderbegin;
for(;qgpointval<inorderend;qgpointval++){
if(inorder[qgpointval]==rootvalue)break;
}
//获得左中序,右中序的下表值
int leftinorderbegin=inorderbegin;
int leftinorderend=qgpointval;
int rightinorderbegin=qgpointval+1;
int rightinorderend=inorderend;
//当我们获取了分割后的中序下表,我们就可以获取前序的下表(中序与前序分割后的数组大小相等)
int leftpreorderbegin=preorderbegin+1;
int leftpreorderend=preorderbegin+1+qgpointval-inorderbegin;
int rightpreorderbegin=preorderbegin+1+qgpointval-inorderbegin;
int rightpreorderend=preorderend;
//遍历循环
root->left=trval(preorder,leftpreorderbegin,leftpreorderend,inorder,leftinorderbegin,leftinorderend);
root->right=trval(preorder,rightpreorderbegin,rightpreorderend,inorder,rightinorderbegin,rightinorderend);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.size()==0||inorder.size()==0)return NULL;
return trval(preorder,0,preorder.size(),inorder,0,inorder.size());
}
};
Leetcode.106.从后序与中序遍历序列构造二叉树
106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode) (leetcode-cn.com)
思路:后续的思路与前序的差不多,只不过是根节点是后序数组的最后一个
代码直接给出
class Solution {
public:
TreeNode* trval(vector<int>&inorder,int inorderbegin,int inorderend,vector<int>&postorder,int postorderbegin,int postorderend){
if(postorderbegin==postorderend)return NULL;
int qgvalue=postorder[postorderend-1];
TreeNode* root=new TreeNode(qgvalue);
if(postorderend-postorderbegin==1)return root;
int qgpoint;
for(qgpoint=0;qgpoint<inorderend;qgpoint++){
if(inorder[qgpoint]==qgvalue)break;
}
int leftinorderbegin=inorderbegin;
int leftinorderend=qgpoint;
int rightinorderbegin=qgpoint+1;
int rightinorderend=inorderend;
int leftpostorderbegin=postorderbegin;
int leftpostorderend=postorderbegin+qgpoint-inorderbegin;
int rightpostorderbegin=postorderbegin+(qgpoint-inorderbegin);
int rightpostorderend=postorderend-1;
root->left=trval(inorder,leftinorderbegin,leftinorderend,postorder,leftpostorderbegin,leftpostorderend);
root->right=trval(inorder,rightinorderbegin,rightinorderend,postorder,rightpostorderbegin,rightpostorderend);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if(inorder.size()==0||postorder.size()==0)return NULL;
return trval(inorder,0,inorder.size(),postorder,0,postorder.size());
}
};
Leetcode.654.最大二叉树
654. 最大二叉树 - 力扣(LeetCode) (leetcode-cn.com)
给定一个不含重复元素的整数数组 nums 。一个以此数组直接递归构建的 最大二叉树 定义如下:
二叉树的根是数组 nums 中的最大元素。
左子树是通过数组中 最大值左边部分 递归构造出的最大二叉树。
右子树是通过数组中 最大值右边部分 递归构造出的最大二叉树。
返回有给定数组 nums 构建的 最大二叉树 。
输入:nums = [3,2,1,6,0,5]
输出:[6,3,5,null,2,0,null,null,1]
解释:递归调用如下所示:
- [3,2,1,6,0,5] 中的最大值是 6 ,左边部分是 [3,2,1] ,右边部分是 [0,5] 。
- [3,2,1] 中的最大值是 3 ,左边部分是 [] ,右边部分是 [2,1] 。
- 空数组,无子节点。
- [2,1] 中的最大值是 2 ,左边部分是 [] ,右边部分是 [1] 。
- 空数组,无子节点。
- 只有一个元素,所以子节点是一个值为 1 的节点。
- [0,5] 中的最大值是 5 ,左边部分是 [0] ,右边部分是 [] 。
- 只有一个元素,所以子节点是一个值为 0 的节点。
- 空数组,无子节点。
思路:这道题思路与上一题的思路差不多。分割数组的思想的运用。我们首先在数组找到最大值作为根节点。根节点之前的数组为左数组用来构建左二叉树,同理右边的用来构建右二叉树
我们采用递归的思路
第一:确定返回类型为TreeNode.参数为数组。由于我们要分割数组,所以我们要设置一个左右标记符,用来结束递归
TreeNode* trval(vector< int >&vec,int left,int right);
第二:终止条件:当left>=right时即数组中只还有一个值时
第三:单层遍历逻辑:我们首先要在数组里面找到最大值作为根节点,然后继续递归获取根节点的左右节点
class Solution {
public:
TreeNode* trval(vector<int>&nums,int left,int right){
//终止条件
if(left>=right)return NULL;
//寻找最大值,并记录其下表
int maxvalueindex=left;
for(int i=left+1;i<right;i++){
if(nums[i]>nums[maxvalueindex]){
maxvalueindex=i;
}
}
//构建节点
TreeNode* root=new TreeNode(nums[maxvalueindex]);
//递归构建
root->left=trval(nums,left,maxvalueindex);
root->right=trval(nums,maxvalueindex+1,right);
return root;
}
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
return trval(nums,0,nums.size());
}
};
Leetcode.617.合并二叉树
617. 合并二叉树 - 力扣(LeetCode) (leetcode-cn.com)
给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。
你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值,否则不为 NULL 的节点将直接作为新二叉树的节点。
示例 1:
输入:
Tree 1 Tree 2
1 2
/ \ / \
3 2 1 3
/ \ \
5 4 7
输出:
合并后的树:
3
/
4 5
/ \ \
5 4 7
注意: 合并必须从两个树的根节点开始
思路:我们采用递归的方式来做这道题。这道题的主要解决问题就是遍历两颗树。我们以一棵树为基本树,在其上面进行修改。
第一:确定返回类型:TreeNode* 参数:由于我们要遍历两颗树那么就是传入两棵树的根节点
第二:终止条件:当一个节点为空时返回另一个节点,另一个节点 为空也没关系,都返回空,两个节点值相加也为空
第三:单层遍历逻辑:就是把第二课树的值赋给第一颗树
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;
}
};