文章目录
- 前言
- 题目
- 解决方案一
- 1.1 思路阐述
- 1.2 源码
- 解决方案二
- 2.1 思路阐述
- 2.2 源码
- 总结
前言
树的题目大概率是要用到递归的,将一个树的问题拆分成子树的问题,不断拆分。
这题也用到了递归的思想。
题目
已知两颗二叉树,将它们合并成一颗二叉树。合并规则是:都存在的结点,就将结点值加起来,否则空的位置就由另一个树的结点来代替。例如:
两颗二叉树是:
数据范围:树上节点数量满足
0
≤
n
≤
500
0≤n≤500
0≤n≤500,树上节点的值一定在32位整型范围内。
进阶:空间复杂度
O
(
1
)
O(1)
O(1),时间复杂度
O
(
n
)
O(n)
O(n)
示例1
输入:{1,3,2,5},{2,1,3,#,4,#,7}
返回值:{3,4,5,5,4,#,7}
示例2
输入:{1},{}
返回值:{1}
解决方案一
1.1 思路阐述
按照题目意思来,这里我一开始审题出现了点问题。题目说的是都存在的节点,我理解存在的节点值。其实题目的意思是,如果根两棵树都存在根节点,那么这两棵树的根节点的值相加。如果两棵树根节点的左节点一棵树存在,一棵树不存在,那么保留存在左节点的那棵树对应的节点。
题目意思理顺了,做的时候就是一个遍历节点的过程了,这里要主要条件的判断。
两种情况:
两棵树没有根节点,返回空;一棵树有节点一棵树没有,返回有节点的那棵树。
当两个节点都存在时,值相加。然后对左右子树执行相同的操作。
这里需要将一棵树作为基本树用来返回。
1.2 源码
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param t1 TreeNode类
* @param t2 TreeNode类
* @return TreeNode类
*/
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
//如果两棵树的根节点都是空则返回
if (!t1 && !t2)
return nullptr;
//以t1为基树,t2为比较树
if (!t1)
return t2;
if (!t2)
return t1;
t1->val += t2->val;
t1->left = mergeTrees(t1->left, t2->left);
t1->right = mergeTrees(t1->right, t2->right);
return t1;
}
};
解决方案二
2.1 思路阐述
上面我写的代码是前序遍历的方式,比较简单。下面这种事官方贴的层次遍历的方法。供参考。
知识点:队列
队列是一种仅支持在表尾进行插入操作、在表头进行删除操作的线性表,插入端称为队尾,删除端称为队首,因整体类似排队的队伍而得名。它满足先进先出的性质,元素入队即将新元素加在队列的尾,元素出队即将队首元素取出,它后一个作为新的队首。
思路:
除了递归的遍历以外,非递归的层次遍历,也可以实现两棵树同步遍历节点相加,重点是两棵树从根节点开始每个节点是同步走的,因此我们可以使用队列辅助两个二叉树分别同时层次遍历。
具体做法:
step 1:首先判断t1与t2是否为空,若为则用另一个代替,若都为空,返回的值也是空。
step 2:使用三个辅助队列,第一个队列q用于暂存合并后的二叉树的层次遍历节点,第二个队列q1用于暂存t1的层次遍历节点,第三个队列q2用于暂存t2的层次遍历节点。
step 3:两棵树同步层次遍历,先将根节点加入队列中,同时根节点优先合并。
step 4:每次从队列分别弹出一个元素,判断分别二者的左右子节点是否存在,若是都存在,则相加合并,若是只存在一个则连接该存在的节点,若是都不存在则连接null。
2.2 源码
class Solution {
public:
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
//若只有一个节点返回另一个,两个都为NULL自然返回NULL
if (t1 == NULL)
return t2;
if (t2 == NULL)
return t1;
//合并根节点
TreeNode* head = new TreeNode(t1->val + t2->val);
//连接后的树的层次遍历节点
queue<TreeNode*> q;
//分别存两棵树的层次遍历节点
queue<TreeNode*> q1;
queue<TreeNode*> q2;
q.push(head);
q1.push(t1);
q2.push(t2);
while (!q1.empty() && !q2.empty()) {
TreeNode *node = q.front(), *node1 = q1.front(), *node2 = q2.front();
q.pop();
q1.pop();
q2.pop();
TreeNode *left1 = node1->left, *left2 = node2->left, *right1 = node1->right, *right2 = node2->right;
//两个左节点都存在
if (left1 || left2) {
if (left1 && left2) {
TreeNode* left = new TreeNode(left1->val + left2->val);
node->left = left;
//新节点入队列
q.push(left);
q1.push(left1);
q2.push(left2);
//只连接一个节点
} else if (left1)
node->left = left1;
else if (left2)
node->left = left2;
}
if (right1 || right2) {
//两个右节点都存在
if (right1 && right2) {
TreeNode* right = new TreeNode(right1->val + right2->val);
node->right = right;
//新节点入队列
q.push(right);
q1.push(right1);
q2.push(right2);
//只连接一个节点
} else if (right1)
node->right = right1;
else
node->right = right2;
}
}
return head;
}
};
总结
树相关的东西,几种遍历方式要烂熟于心。还有就是递归一般都是优先解法。