|
| 1 | +// ✅ Time Complexity: O(m * n) (due to the substring search), where m is the number of nodes in root and n is the number of nodes in subRoot. |
| 2 | +// ✅ Space Complexity: O(m + n) |
| 3 | + |
| 4 | +/** |
| 5 | + * Definition for a binary tree node. |
| 6 | + * function TreeNode(val, left, right) { |
| 7 | + * this.val = (val===undefined ? 0 : val) |
| 8 | + * this.left = (left===undefined ? null : left) |
| 9 | + * this.right = (right===undefined ? null : right) |
| 10 | + * } |
| 11 | + */ |
| 12 | +/** |
| 13 | + * @param {TreeNode} root |
| 14 | + * @param {TreeNode} subRoot |
| 15 | + * @return {boolean} |
| 16 | + */ |
| 17 | +var isSubtree = function (root, subRoot) { |
| 18 | + // Helper function: Serializes a tree into a string representation in a pre-order fashion |
| 19 | + // by visiting the node first, then left and right subtrees. This ensures each node is uniquely |
| 20 | + // represented with its value, and the structure is captured recursively. |
| 21 | + const serialize = (node) => { |
| 22 | + if (!node) return "#"; // Use "#" to represent null nodes, ensuring we capture structure. |
| 23 | + return `(${node.val},${serialize(node.left)},${serialize(node.right)})`; // Recursively serialize left and right children. |
| 24 | + }; |
| 25 | + |
| 26 | + const serializedRoot = serialize(root); // O(m) for serializing root. |
| 27 | + const serializedSubRoot = serialize(subRoot); // O(n) for serializing subRoot. |
| 28 | + |
| 29 | + return serializedRoot.includes(serializedSubRoot); // O(m * n) for the substring search. |
| 30 | +}; |
| 31 | + |
| 32 | + |
| 33 | + |
| 34 | +// ✅ Time Complexity: O(m * n), where m is the number of nodes in root and n is the number of nodes in subRoot. |
| 35 | +// ✅ Space Complexity: O(m + n), due to the recursion stack for both isSubtree and isSameTree. |
| 36 | + |
| 37 | +/** |
| 38 | + * Definition for a binary tree node. |
| 39 | + * function TreeNode(val, left, right) { |
| 40 | + * this.val = (val===undefined ? 0 : val) |
| 41 | + * this.left = (left===undefined ? null : left) |
| 42 | + * this.right = (right===undefined ? null : right) |
| 43 | + * } |
| 44 | + */ |
| 45 | +/** |
| 46 | + * @param {TreeNode} root |
| 47 | + * @param {TreeNode} subRoot |
| 48 | + * @return {boolean} |
| 49 | + */ |
| 50 | +// var isSubtree = function (root, subRoot) { |
| 51 | +// // Base case: if root is null, subRoot can't be a subtree |
| 52 | +// if (!root) return false; |
| 53 | + |
| 54 | +// // Helper function to check if two trees are identical |
| 55 | +// const isSameTree = (node1, node2) => { |
| 56 | +// if (!node1 && !node2) return true; // Both are null, they are identical |
| 57 | +// if (!node1 || !node2) return false; // One is null, other is not, they are not identical |
| 58 | + |
| 59 | +// if (node1.val !== node2.val) return false; // Values don't match, not identical |
| 60 | + |
| 61 | +// // Recursively check both left and right subtrees |
| 62 | +// return ( |
| 63 | +// isSameTree(node1.left, node2.left) && isSameTree(node1.right, node2.right) |
| 64 | +// ); |
| 65 | +// }; |
| 66 | + |
| 67 | +// // If the current node of root is identical to subRoot, return true |
| 68 | +// if (isSameTree(root, subRoot)) return true; |
| 69 | + |
| 70 | +// // isSubtree is true if subRoot exists as a subtree in either the left or right side of root. |
| 71 | +// // It checks both sides recursively until it finds a match, and if found, returns true. |
| 72 | +// // If it doesn't find a match in either subtree, it will return false. |
| 73 | +// return isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); |
| 74 | +// }; |
| 75 | + |
| 76 | + |
0 commit comments