Leetcode106——从中序与后续遍历序列构造二叉树
题目描述:
给定两个整数数组 inorder
和 postorder
,其中 inorder
是二叉树的中序遍历, postorder
是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
示例 1:
输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3] 输出:[3,9,20,null,null,15,7]
示例 2:
输入:inorder = [-1], postorder = [-1] 输出:[-1]
算法思想:
通过递归的思想,利用后续遍历序列寻找到根节点(后序序列中最后一个节点),从而去对应中序遍历序列中划分左右子树(根节点左边的为左子树,右边的为右子树)。
算法实现:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if(postorder.size()==0) return nullptr;
int rootvalue=postorder[postorder.size()-1];
TreeNode* root=new TreeNode(rootvalue);
if(postorder.size()==1) return root;
int index=-1;
while(inorder[++index]!=rootvalue);
vector<int> linorder;
vector<int> rinorder;
for(int i=0;i<index;i++) linorder.push_back(inorder[i]);
for(int i=index+1;i<inorder.size();i++) rinorder.push_back(inorder[i]);
vector<int> lpostorder;
vector<int> rpostorder;
for(int i=0;i<linorder.size();i++) lpostorder.push_back(postorder[i]);
for(int i=linorder.size();i<postorder.size()-1;i++)
rpostorder.push_back(postorder[i]);
root->left=buildTree(linorder,lpostorder);
root->right=buildTree(rinorder,rpostorder);
return root;
}
Leetcode105——从前序与中续遍历序列构造二叉树
题目描述:
给定两个整数数组 preorder
和 inorder
,其中 preorder
是二叉树的先序遍历, inorder
是同一棵树的中序遍历,请构造二叉树并返回其根节点。
示例 1:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7] 输出: [3,9,20,null,null,15,7]
示例 2:
输入: preorder = [-1], inorder = [-1] 输出: [-1]
算法思想:
与上题差不多,不过是通过前序去寻找根节点,在做相应的划分。不多赘述了。
算法实现:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.size()==0) return nullptr;
int rootvalue=preorder[0];
TreeNode* root=new TreeNode(rootvalue);
if(preorder.size()==1) return root;
int index=-1;
while(inorder[++index]!=rootvalue);
vector<int> lInorder,rInorder,lPreorder,rPreorder;
for(int i=0;i<index;i++) lInorder.push_back(inorder[i]);
for(int i=index+1;i<inorder.size();i++) rInorder.push_back(inorder[i]);
for(int i=0;i<lInorder.size();i++) lPreorder.push_back(preorder[i+1]);
for(int i=lInorder.size()+1;i<preorder.size();i++)
rPreorder.push_back(preorder[i]);
root->left=buildTree(lPreorder,lInorder);
root->right=buildTree(rPreorder,rInorder);
return root;
}
Leetcode654——最大二叉树
题目描述:
给定一个不重复的整数数组 nums
。 最大二叉树 可以用下面的算法从 nums
递归地构建:
- 创建一个根节点,其值为
nums
中的最大值。 - 递归地在最大值 左边 的 子数组前缀上 构建左子树。
- 递归地在最大值 右边 的 子数组后缀上 构建右子树。
返回 nums
构建的 最大二叉树 。
示例 1:
输入: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* constructMaximumBinaryTree(vector<int>& nums) {
if(nums.size()==0) return nullptr;
int max=nums[0],index=0;
for(int i=0;i<nums.size();i++){
if(nums[i]>max){
max=nums[i];
index=i;
}
}
TreeNode* root=new TreeNode(max);
if(nums.size()==1) return root;
vector<int> ltree,rtree;
for(int i=0;i<index;i++) ltree.push_back(nums[i]);
for(int i=index+1;i<nums.size();i++) rtree.push_back(nums[i]);
root->left=constructMaximumBinaryTree(ltree);
root->right=constructMaximumBinaryTree(rtree);
return root;
}
事实证明他还是如此的慢,没法子,绝望两个字已不想多说。
TreeNode* buildTree(vector<int> nums,int start,int end){
if(end==start) return nullptr;
int max=nums[start],index=start;
for(int i=start;i<end;i++){
if(nums[i]>max){
max=nums[i];
index=i;
}
}
TreeNode* root=new TreeNode(max);
if(end-start==1) return root;
root->left=buildTree(nums,start,index);
root->right=buildTree(nums,index+1,end);
return root;
}
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
return buildTree(nums,0,nums.size());
}
Leetcode617——合并二叉树
题目描述:
给你两棵二叉树: root1
和 root2
。
想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。
返回合并后的二叉树。
注意: 合并过程必须从两个树的根节点开始。
示例 1:
输入:root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7] 输出:[3,4,5,5,4,null,7]
算法思想:
利用先序遍历的思想同时遍历两棵树,并将其节点合并。毁灭吧,都好慢啊。
算法实现:
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
TreeNode* root;
if(root1==nullptr && root2==nullptr) return nullptr;
else if(root1==nullptr || root2==nullptr){
if(root1) return root1;
if(root2) return root2;
}
else{
root=new TreeNode(root1->val+root2->val);
}
root->left=mergeTrees(root1->left,root2->left);
root->right=mergeTrees(root1->right,root2->right);
return root;
}
Leetcode700——二叉搜索树中的搜索
题目描述:
给定二叉搜索树(BST)的根节点 root
和一个整数值 val
。
你需要在 BST 中找到节点值等于 val
的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null
。
示例 1:
输入:root = [4,2,7,1,3], val = 2 输出:[2,1,3]
算法思想:
利用二叉搜索树的特性左小右大。在遍历时比较当前节点与目标节点的值,若大于目标值向左子树遍历,若小于目标值向右子树遍历。
算法实现:
TreeNode* searchBST(TreeNode* root, int val) {
if(!root) return NULL;
TreeNode* node;
if(root->val==val) return root;
else if(root->val>val) node=searchBST(root->left,val);
else node=searchBST(root->right,val);
return node;
}
Leetcode98——验证二叉搜索树
题目描述:
给你一个二叉树的根节点 root
,判断其是否是一个有效的二叉搜索树。
有效 二叉搜索树定义如下:
- 节点的左
子树
只包含 小于 当前节点的数。 - 节点的右子树只包含 大于 当前节点的数。
- 所有左子树和右子树自身必须也是二叉搜索树。
示例 1:
输入:root = [2,1,3] 输出:true
示例 2:
输入:root = [5,1,4,null,null,3,6] 输出:false 解释:根节点的值是 5 ,但是右子节点的值是 4 。
算法思想:
利用二叉搜索树的特性,中序遍历遍历出的顺序是个升序序列。不要以为左孩子小右孩子大就完事了,我就是这么想的,弄了好一会。是左子树小右子树大。
算法实现:
TreeNode* pre=nullptr;
bool isValidBST(TreeNode* root) {
if(root==nullptr) return true;
bool ltree=isValidBST(root->left);
if(pre!=nullptr && pre->val>=root->val) return false;
pre=root;
bool rtree=isValidBST(root->right);
return ltree&&rtree;
}