This problem asks to determine if two binary expression trees are equivalent. Two trees are considered equivalent if they evaluate to the same value regardless of the variable assignments. The trees only use the '+' operator.
The most efficient approach leverages Depth-First Search (DFS) and a counter. Instead of evaluating the expressions directly, we count the occurrences of each variable in each tree. If the counts match for every variable, the trees are equivalent.
Algorithm:
root1
and decrement it in a counter for root2
.Time Complexity Analysis:
The time complexity is O(N), where N is the total number of nodes in both trees. This is because the DFS traversal visits each node exactly once.
Space Complexity Analysis:
The space complexity is O(A), where A is the number of unique variables (letters) in the trees. This is due to the space used by the counter to store the counts. In the worst case, A could be equal to N (all nodes are distinct variables), but generally A will be smaller than N. The recursive call stack during DFS adds a small space overhead proportional to the height of the trees (in the worst case, O(N) for skewed trees).
from collections import Counter
class Solution:
def checkEquivalence(self, root1: 'Node', root2: 'Node') -> bool:
def dfs(root, v):
if root is None:
return
if root.val != '+':
cnt[root.val] += v
dfs(root.left, v)
dfs(root.right, v)
cnt = Counter()
dfs(root1, 1)
dfs(root2, -1)
return all(x == 0 for x in cnt.values())
checkEquivalence(root1, root2)
: This is the main function. It initializes a Counter
object (cnt
) to store variable counts. It calls dfs
on both root1
(incrementing counts) and root2
(decrementing counts). Finally, it checks if all counts are zero.
dfs(root, v)
: This function performs the depth-first search.
if root is None:
: Handles the base case of an empty subtree.if root.val != '+':
: If the node is a variable, update the count in the cnt
counter by v
(1 for root1
, -1 for root2
).dfs(root.left, v)
and dfs(root.right, v)
: Recursively calls dfs
on the left and right subtrees.all(x == 0 for x in cnt.values())
: This efficiently checks if all values in the cnt
counter are zero, indicating that variable counts are equal in both trees.
The other language implementations (Java, C++, JavaScript) follow a similar structure, adapting the syntax and data structures to their respective languages. Solution 2 provides a slightly different approach to achieve the same outcome. Both solutions are asymptotically optimal.