思路:
题目的主要信息:
- 合并(相加)二叉树位置相同的结点
- 缺少的结点用另一棵树来补,若都缺则返回NULL
方法一:递归先序遍历
同时先序遍历两棵树即可完成。
具体做法:
首先判断t1与t2是否为空,若为则用另一个代替,若都为空,返回的值也是空。然后依据先序遍历的特点,根左右的顺序递归访问。
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);
head->left = mergeTrees(t1->left, t2->left);
head->right = mergeTrees(t1->right, t2->right);
return head;
}
};
复杂度分析:
- 时间复杂度:O(min(n,m)),m和n分别为两棵树的结点树,当一个树访问完时,自然就连接上另一个树的结点,故只访问了小树的结点数。
- 空间复杂度:O(min(n,m)),递归栈深度也同时间,只访问了小树的结点数。
方法二:非递归层次遍历
具体做法:
使用三个辅助队列,第一个队列q用于暂存合并后的二叉树的层次遍历结点,第二个队列q1用于暂存t1的层次遍历结点,第三个队列q2用于暂存t2的层次遍历结点。 层次遍历两棵树,判断分别二者的左右子结点是否存在,若是都存在,则相加合并,若是只存在一个则连接该存在的结点,若是都不存在则连接NULL。
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;
}
};
复杂度分析:
- 时间复杂度:O(min(n,m)),m和n分别为两棵树的结点树,当一个树访问完时,自然就连接上另一个树的结点,故只访问了小树的结点数。
- 空间复杂度:O(min(n,m)),辅助队列同时间,只访问了小树的结点数。