|
| 1 | +# Subtree of Another Tree |
| 2 | + |
| 3 | +#### Difficulty in LeetCode |
| 4 | + |
| 5 | + |
| 6 | +#### Difficulty of understanding complexity |
| 7 | + |
| 8 | + |
| 9 | +Given two non-empty binary trees `s` and `t`, check whether tree t has exactly the same structure and node values with a subtree of `s`. A subtree of `s` is a tree consists of a node in `s` and all of this node's descendants. The tree `s` could also be considered as a subtree of itself. |
| 10 | + |
| 11 | + |
| 12 | +## Example 1: |
| 13 | + |
| 14 | +``` |
| 15 | +Given tree s: |
| 16 | +
|
| 17 | + 3 |
| 18 | + / \ |
| 19 | + 4 5 |
| 20 | + / \ |
| 21 | + 1 2 |
| 22 | +Given tree t: |
| 23 | + 4 |
| 24 | + / \ |
| 25 | + 1 2 |
| 26 | +Return true, because t has the same structure and node values with a subtree of s. |
| 27 | +``` |
| 28 | + |
| 29 | +## Example 2: |
| 30 | + |
| 31 | +``` |
| 32 | +Given tree s: |
| 33 | +
|
| 34 | + 3 |
| 35 | + / \ |
| 36 | + 4 5 |
| 37 | + / \ |
| 38 | + 1 2 |
| 39 | + / |
| 40 | + 0 |
| 41 | +Given tree t: |
| 42 | + 4 |
| 43 | + / \ |
| 44 | + 1 2 |
| 45 | +Return false. |
| 46 | +``` |
| 47 | + |
| 48 | +## Complexity Analysis (Recursive Comparision Approach): |
| 49 | + |
| 50 | +- **Time complexity** : `O(m * n)`. Where `n` is number of nodes in **s** and `m` is number of nodes in **t**. |
| 51 | + |
| 52 | +An alternative approach is to search through the larger tree, Tl , Each time a node in Tl matches the root of T2, call `isSameTree`. The matchTree method will compare the two subtrees to see if they are identical. Analyzing the runtime is somewhat complex. A naive answer would be to say that it is 0(nm) time, where n is the number of nodes in Tl and m is the number of nodes in T2. While this is technically correct, a little more thought can produce a tighter bound |
| 53 | + |
| 54 | + |
| 55 | + * I think it's because in the worst case, the `isSameTree` method is called for each node. The `isSameTree` method will be O(n) with `n` being the size of the smaller tree. You are calling this `m` times with m being the size of the larger tree, so O(m)O(n) = O(mn) |
| 56 | + * If the every element in the bigger tree contains same elements as the smaller tree, each time we need to compare until we find that the smaller tree reaches null but bigger tree's branch not. This process is persistence among all of the tree, so it would be m times n |
| 57 | + * For Approach#2 O(mn) is definitely overestimating. The upper bound is closer to O(m + kn) where k is the number of nodes for which the root of t matches the value of the node of s that's just being traversed. To prove this point let's rewrite the traverse method slightly differently and add s.val == t.val && before the equals(s, t) call. Now it's clearer that equals is doing work only when the root of t matches the current node of s. How much work will it do? If the 2 trees match, it will do O(n) work. Otherwise, on any mismatch we'll break early so even O(m + k*n) is an over estimate. |
| 58 | + * It's more complicated than that. If all n nodes match the root of the t, then traverse will no longer do O(n) work, unless t itself is also equal to all the same values. But then, it will only do that O(n) work once because of the ||. CTCI solution discusses this problem a little more in depth and looks at the runtime in a probabilistic fashion and proves this point. |
| 59 | +- **Space complexity** : `O(log(n)) - best, o(n) worst`. The best case is for a completely balanced tree. The worst case is for an unbalanced tree. The space is to keep a recursion stack. `n` is number of nodes in **s**. |
| 60 | + |
| 61 | +#### [LeetCode link](https://leetcode.com/problems/subtree-of-another-tree/) |
0 commit comments