Design Gurus Logo
Blind 75

Problem Statement

Given the roots of two binary trees 'p' and 'q', write a function to check if they are the same or not.

Two binary trees are considered the same if they met following two conditions:

  1. Both tree are structurally identical.
  2. Each corresponding node on both the trees have the same value.

Example 1:

Given the following two binary trees:

Image

Output: true

Explanation: Both trees are structurally identical and have same values.

Example 2:

Given the following two binary trees:

Image

Output: false

Explanation: Trees are structurally different.

Example 3:

Given the following two binary trees:

Image

Output: false

Explanation: Corresponding nodes have different value ( 4 & 9 ).

Constraints:

  • The number of nodes in both trees is in the range [0, 100].
  • -10<sup>4</sup> <= Node.val <= 10<sup>4</sup>

Why this is a Multi-threaded problem

What the question saysThe signal it matches
"check if they are the same or not"each part produces a separate result that combines simply, here a boolean
"Both tree are structurally identical"the recursion has two branches that never read each other's data

This is the compare two structures variant: the left pair and the right pair are checked at the same time.

The closest alternative. The ordinary recursive comparison on one thread, and on this input it is the better answer. The trees hold at most 100 nodes, which is the case the introduction rules out: thread setup then costs more than the work.

What the problem teaches is the shape that makes parallel work safe at all. The left pair and the right pair never touch each other's nodes, and neither writes anything. So the two branches can run at the same time with no lock. Their results combine with a single and. Solve it single threaded first, as the introduction insists, then say which parts could run at once and why nothing needs protecting.

Solution

A simple solution would be to recursively check each corresponding node of the two trees. If one of the trees do not have a corresponding node or their values differ, we can conclude that the trees are not the same.

Code

Here is what our algorithm will look like:

mediaLink

p = [1, 2, 3], q = [1, 2, 3]. Recursively compare corresponding nodes: values must match, and both subtrees (left and right) must have the same structure.

1 of 9

Python3
Python3

Time Complexity

The solution will take O(min(M, N)) time, where 'M' and 'N' are the number of nodes in the given trees respectively. We are taking minimum of 'M' and 'N', since as soon as we see a difference in value or structure, we do not check the remaining trees.

Space Complexity

The recursion stack holds at most one node per level, so we need O(H) space, where H is the height of the given tree. In the worst case the tree is a linked list, the height equals the number of nodes, and the same bound reads as O(N).

Making the Algorithm Multi-threaded

To further improve the algorithm, we can make isSameTree() multi-threaded to check the left and right subtrees in separate threads.

We can find how many processors the machine has on which our algorithm is running. We will, then, start multiple threads so that each core can run one thread.

We will use a Volatile Boolean variable isSame so that multiple threads can update its value concurrently.

Here is the code that takes care of this scenario:

Python3
Python3

Time and Space Complexities

Everything has the same complexity as the previous solution.

What actually runs in parallel

The threaded version does not behave the same way in every language. In CPython the global interpreter lock lets only one thread run Python bytecode at a time, so the threads here take turns rather than run together, and the code shows the shape of the pattern rather than a speedup. To get real parallelism in Python you would use multiprocessing, or a build of the interpreter with the lock removed. JavaScript has the same limit with its single event loop, which is why the threaded version is not shown there. Java, C++, C# and Go do walk the two subtrees at the same time.

One build note for C++: std::thread needs the threads library at link time. If you compile the code yourself, add -pthread to the command, or the linker will report an undefined reference to pthread_create.

No code editor for this lesson
This lesson focuses on concepts and theory