多一些Aha Time,发现技术的美妙🍺|

啊原来是这样呀

园龄:8年3个月粉丝:3关注:9

【LeetCode】11.二叉树系列——构造与修改

总目录:

LeetCode系列导航目录

 

0.理论基础

0.1.根据前/中/后序遍历结果中的2个来构建树

前提:

前序和后序不能用来构建树,因为不能切割左右子树的范围。

步骤:

(1)确认根节点;

(2)切割数组;

(3)递归构建左右子树;

构造二叉树有三个注意的点:

(1)分割时候,坚持区间不变量原则,左闭右开,或者左闭右闭;

(2)分割的时候,注意后序 或者 前序已经有一个节点作为中间节点了,不能继续使用了;

(3)如何使用切割后的后序数组来切合中序数组?利用中序数组大小一定是和后序数组的大小相同这一特点来进行切割。

0.2.要点

222

0.3.代码实例

333

 

1.从中序和后序遍历序列构建二叉树

1.1.问题描述

给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。

 

 


链接:https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal

1.2.要点

根节点是后序遍历的最后一个

1.3.代码实例

递归

复制代码
 1 class Solution {
 2 public:
 3     TreeNode* build(vector<int>& inorder,int start1,int end1,
 4     vector<int>& postorder,int start2,int end2){
 5         if(start1>end1||start2>end2){
 6             return NULL;
 7         }
 8 
 9         //后序遍历最后一个节点是根节点
10         TreeNode* root=new TreeNode(postorder[end2]);
11 
12         //找到根节点在中序遍历中的序号
13         int rootInOrder=start1;
14         while(inorder[rootInOrder]!=postorder[end2]){
15             rootInOrder++;
16         }
17         
18         //切割左树
19         int newStart1=start1;
20         int newEnd1=rootInOrder-1;
21         int newStart2=start2;
22         int newEnd2=start2+(rootInOrder-1-start1);
23         root->left=build(inorder,newStart1,newEnd1,postorder,newStart2,newEnd2);
24 
25         //切割右树
26         newStart1=rootInOrder+1;
27         newEnd1=end1;
28         newStart2=start2+(rootInOrder-1-start1)+1;
29         newEnd2=end2-1;   
30         root->right=build(inorder,newStart1,newEnd1,postorder,newStart2,newEnd2);
31         
32         return root;
33     }
34     TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
35         int dataLen1=inorder.size();
36         int dataLen2=postorder.size();
37         if(inorder.size()<=0||postorder.size()<=0){
38             return NULL;
39         }
40 
41         return build(inorder,0,postorder.size()-1,postorder,0,postorder.size()-1);   
42     }
43 };
View Code
复制代码

 

2.从前序和中序遍历序列构建二叉树

2.1.问题描述

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

链接:https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal

2.2.要点

前序遍历的第一个节点是根节点

2.3.代码实例

递归

复制代码
 1 class Solution {
 2 public:
 3     TreeNode* build(vector<int>& preorder,int start1,int end1,
 4     vector<int>& inorder,int start2,int end2){
 5         if(start1>end1||start2>end2){
 6             return NULL;
 7         }
 8 
 9         //前序遍历第一个节点是根节点
10         TreeNode* root=new TreeNode(preorder[start1]);
11 
12         //找到根节点在中序遍历中的序号
13         int rootInOrder=start2;
14         while(inorder[rootInOrder]!=preorder[start1]){
15             rootInOrder++;
16         }
17         
18         //切割左树
19         int newStart2=start2;
20         int newEnd2=rootInOrder-1;
21         int newStart1=start1+1;
22         int newEnd1=start1+1+(newEnd2-newStart2);
23         root->left=build(preorder,newStart1,newEnd1,inorder,newStart2,newEnd2);
24 
25         //切割右树
26         newStart2=rootInOrder+1;
27         newEnd2=end2;   
28         newStart1=newEnd1+1;
29         newEnd1=end1;
30 
31         root->right=build(preorder,newStart1,newEnd1,inorder,newStart2,newEnd2);
32         
33         return root;
34     }
35     TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
36         int dataLen1=preorder.size();
37         int dataLen2=inorder.size();
38         if(preorder.size()<=0||inorder.size()<=0){
39             return NULL;
40         }
41 
42         return build(preorder,0,preorder.size()-1,inorder,0,inorder.size()-1); 
43     }
44 };
View Code
复制代码

 

3.最大二叉树

3.1.问题描述

给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建:
(1)创建一个根节点,其值为 nums 中的最大值。
(2)递归地在最大值 左边 的 子数组前缀上 构建左子树。
(3)递归地在最大值 右边 的 子数组后缀上 构建右子树。
返回 nums 构建的 最大二叉树 。
链接:https://leetcode.cn/problems/maximum-binary-tree

3.2.要点

递归,进阶是降低搜索最大值的时间复杂度

3.3.代码实例

递归

复制代码
 1 class Solution {
 2 public:
 3     TreeNode* build(vector<int>& nums,int start,int end){
 4         if(start>end){
 5             return NULL;
 6         }
 7 
 8         //寻找最大值
 9         int maxVal=INT_MIN;
10         int maxId=-1;
11         for(int i=start;i<=end;i++){
12             if(nums[i]>maxVal){
13                 maxVal=nums[i];
14                 maxId=i;
15             }
16         }
17 
18         //构建根节点,及左右子树
19         TreeNode* root=new TreeNode(maxVal);
20         root->left=build(nums,start,maxId-1);
21         root->right=build(nums,maxId+1,end);
22 
23         return root;
24     }
25     TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
26         int dataLen=nums.size();
27         if(dataLen<=0){
28             return NULL;
29         }
30 
31         return build(nums,0,dataLen-1);
32     }
33 };
View Code
复制代码

 

4.合并二叉树

4.1.问题描述

给你两棵二叉树: root1 和 root2 。
想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。
返回合并后的二叉树。
注意: 合并过程必须从两个树的根节点开始。

 

 链接:https://leetcode.cn/problems/merge-two-binary-trees

4.2.要点

1递归

2迭代,递归的栈版本

3迭代,层序遍历

4.3.代码实例

递归

复制代码
 1 class Solution {
 2 public:
 3     
 4     TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
 5         TreeNode* newNode=NULL;
 6         if(root1==NULL&&root2==NULL){
 7             newNode= NULL;
 8         }
 9         else if(root1==NULL&&root2!=NULL){
10             newNode=root2;
11         }
12         else if(root1!=NULL&&root2==NULL){
13             newNode=root1;
14         }
15         else{
16             newNode=root2;
17             root2->val=root1->val+root2->val;
18             root2->left=mergeTrees(root1->left,root2->left);
19             root2->right=mergeTrees(root1->right,root2->right);
20         }
21 
22         return newNode;
23     }
24 };
View Code
复制代码

迭代,递归的栈版本

复制代码
 1 class Solution {
 2 public:    
 3     TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
 4         if(!root1)
 5             return root2;
 6         if(!root2)
 7             return root1;
 8         
 9         stack<pair<TreeNode*, TreeNode*>> stk;
10         stk.push(pair<TreeNode*,TreeNode*>(root1,root2));
11 
12         while(stk.size()){
13             auto p = stk.top();
14             auto p1 = p.first, p2 = p.second;
15             stk.pop();
16             p1->val += p2->val;
17 
18             if(p1->left && p2->left){
19                 stk.push({p1->left, p2->left});
20             }
21             if(p1->right && p2->right){
22                 stk.push({p1->right,p2->right});
23             }
24             if(!p1->left && p2->left){
25                 p1->left = p2->left;
26             }
27             if(!p1->right && p2->right){
28                 p1->right = p2->right;
29             }
30         }
31         return root1;
32     }
33 };
View Code
复制代码

迭代,层序遍历

复制代码
 1 class Solution {
 2     public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
 3     //如果 t1和t2中,只要有一个是null,函数就直接返回
 4         if(t1==null || t2==null) {
 5             return t1==null? t2 : t1;
 6         }
 7         java.util.LinkedList<TreeNode> queue = new java.util.LinkedList<TreeNode>();
 8         queue.add(t1);
 9         queue.add(t2);
10         while(queue.size()>0) {
11             TreeNode r1 = queue.remove();
12             TreeNode r2 = queue.remove();
13             r1.val += r2.val;
14             //如果r1和r2的左子树都不为空,就放到队列中
15             //如果r1的左子树为空,就把r2的左子树挂到r1的左子树上
16             if(r1.left!=null && r2.left!=null){
17                 queue.add(r1.left);
18                 queue.add(r2.left);
19             }
20             else if(r1.left==null) {
21                 r1.left = r2.left;
22             }
23             //对于右子树也是一样的
24             if(r1.right!=null && r2.right!=null) {
25                 queue.add(r1.right);
26                 queue.add(r2.right);
27             }
28             else if(r1.right==null) {
29                 r1.right = r2.right;
30             }
31         }
32         return t1;
33     }
34 }
View Code
复制代码

 

 

 

xxx.问题

xxx.1.问题描述

111

xxx.2.要点

222

xxx.3.代码实例

333

本文作者:啊原来是这样呀

本文链接:https://www.cnblogs.com/OhOfCourse/p/16989527.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   啊原来是这样呀  阅读(16)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起