一、 题目描述
题目大意:已知两颗二叉树,将它们合并成一颗二叉树。合并规则是:都存在的结点,就将结点值加起来,否则空的位置就由另一个树的结点来代替。
二、算法1(层序遍历)
解题思路
- 对两颗二叉树同时进行层序遍历,使用到了队列,不过节点入队的条件为两节点存在,若t1存在t2不存在,则跳过;若t2存在t1不存在,则将t1的父节点指针指向t2
- 规定两节点入队时,t1的节点在前,保证取出的第一个节点是t1的,第二个节点是t2的
代码实现(C++11)
class Solution { public: TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) { if(!t1) return t2; if(!t2) return t1; queue<TreeNode*> q; q.push(t1); q.push(t2); while (q.size()) { TreeNode* root1 = q.front(); q.pop(); TreeNode* root2 = q.front(); q.pop(); // 以t1的节点为基准 root1->val += root2->val; // 若root1和root2的左儿子都存在, 加入队列 if (root1->left && root2->left) { q.push(root1->left); q.push(root2->left); } // 若root1和root2的右儿子都存在, 加入队列 if (root1->right && root2->right) { q.push(root1->right); q.push(root2->right); } // 若root1的左儿子不存在, t2的左儿子存在, root1的左儿子换成t2的左儿子 if(!root1->left && root2->left) { root1->left = root2->left; } // 若root1的右儿子不存在, root2的右儿子存在, root1的右儿子换成root2的右儿子 if(!root1->right && root2->right) { root1->right = root2->right; } } return t1; } };
时间复杂度:,n为两颗二叉树最少的节点数,进行一次层序遍历
空间复杂度:,n为两颗二叉树最少的节点数,最坏情况下两颗二叉树都是完全二叉树
三、算法2(前序遍历)
解题思路
- 与层序遍历的基本思路相同,对两颗二叉树同时进行遍历
- 当相同位置都存在节点时,将t2节点的值加在t1节点上,若t1为空,则返回t2当前节点指针;若t2为空,则返回t1当前节点指针;最后返回t1即可
代码实现(C++11)
class Solution { public: TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) { if(!t1) return t2; if(!t2) return t1; // 以t1为主要参考 t1->val += t2->val; // 同时向左递归 t1->left = mergeTrees(t1->left, t2->left); // 同时向右递归 t1->right = mergeTrees(t1->right, t2->right); return t1; } };
时间复杂度:,n为两颗二叉树最少的节点数,遍历一次的时间复杂度为O(n)
空间复杂度:,m为二叉树的高度,递归使用的栈空间为m