# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def mergeTrees(self, t1: TreeNode, t2: TreeNode) -> TreeNode:
if not t1 and not t2:
return None
if not t1:
return t2
if not t2:
return t1
merged = TreeNode(t1.val + t2.val)
merged.left = self.mergeTrees(t1.left, t2.left)
merged.right = self.mergeTrees(t1.right, t2.right)
return merged
// Definition for a binary tree node.
// struct TreeNode {
// int val;
// TreeNode *left;
// TreeNode *right;
// TreeNode() : val(0), left(nullptr), right(nullptr) {}
// TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
// TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
// };
class Solution {
public:
TreeNode* mergeTrees(TreeNode* t1, TreeNode* t2) {
if (!t1 && !t2) return nullptr;
if (!t1) return t2;
if (!t2) return t1;
TreeNode* merged = new TreeNode(t1->val + t2->val);
merged->left = mergeTrees(t1->left, t2->left);
merged->right = mergeTrees(t1->right, t2->right);
return merged;
}
};
// Definition for a binary tree node.
// public class TreeNode {
// int val;
// TreeNode left;
// TreeNode right;
// TreeNode() {}
// TreeNode(int val) { this.val = val; }
// TreeNode(int val, TreeNode left, TreeNode right) {
// this.val = val;
// this.left = left;
// this.right = right;
// }
// }
class Solution {
public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
if (t1 == null && t2 == null) return null;
if (t1 == null) return t2;
if (t2 == null) return t1;
TreeNode merged = new TreeNode(t1.val + t2.val);
merged.left = mergeTrees(t1.left, t2.left);
merged.right = mergeTrees(t1.right, t2.right);
return merged;
}
}
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} t1
* @param {TreeNode} t2
* @return {TreeNode}
*/
var mergeTrees = function(t1, t2) {
if (!t1 && !t2) return null;
if (!t1) return t2;
if (!t2) return t1;
let merged = new TreeNode(t1.val + t2.val);
merged.left = mergeTrees(t1.left, t2.left);
merged.right = mergeTrees(t1.right, t2.right);
return merged;
};
You are given two binary trees, t1
and t2
. You need to merge them into a new binary tree. The merging rule is simple: if two nodes overlap (i.e., both trees have a node at the same position), their values are summed and become the value of the new node in the merged tree. If only one tree has a node at a given position, that node is used directly in the merged tree.
The function should return the root of the new merged tree. The input trees are not modified, and you should not reuse the nodes from the original trees in the merged tree.
null
).At first glance, merging two binary trees might seem complicated, especially if you try to handle all possible tree shapes and missing nodes at once. A brute-force approach could involve traversing both trees separately and then combining their results, but this quickly becomes messy.
However, if you think recursively, the problem becomes much more manageable. For each position in the trees, you can:
This recursive strategy naturally handles trees of different shapes and sizes, and it avoids unnecessary complexity.
We use a recursive algorithm to merge the two trees. Here’s a step-by-step breakdown:
null
, return null
(no node to merge).null
, return the non-null
node (no merging needed).This approach is elegant because it mirrors the structure of the trees and handles all cases in a clean, readable way.
Consider the following input trees:
Tree 1: 1 / \ 3 2 / 5 Tree 2: 2 / \ 1 3 \ \ 4 7
Let's merge them step-by-step:
The merged tree:
3 / \ 4 5 / \ \ 5 4 7
Each step only considers the current pair of nodes, and the recursion takes care of the rest.
The recursive approach is optimal because it only processes each node once and uses space proportional to the tree's height.
To merge two binary trees, a recursive solution elegantly handles all cases by summing overlapping nodes and reusing existing nodes when only one exists. This approach is both simple and efficient, with clear base cases and recursive steps that mirror the structure of the trees. The algorithm is optimal in both time and space, making it an excellent example of using recursion to solve tree problems.