diff --git a/README.md b/README.md index eaba452..f4a7751 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,7 @@ My approach to solving LeetCode problems typically involves the following steps: | 67 | [Add Binary](https://leetcode.com/problems/add-binary/) | Algorithms | [TypeScript](./problems/algorithms/addBinary/AddBinary.ts) | Easy | | 559 | [Maximum Depth of N-ary Tree](https://leetcode.com/problems/maximum-depth-of-n-ary-tree/) | Algorithms | [TypeScript](./problems/algorithms/maximumDepthOfNAryTree/MaximumDepthOfNAryTree.ts) | Easy | | 563 | [Binary Tree Tilt](https://leetcode.com/problems/binary-tree-tilt/) | Algorithms | [TypeScript](./problems/algorithms/binaryTreeTilt/BinaryTreeTilt.ts) | Easy | +| 572 | [Subtree of Another Tree](https://leetcode.com/problems/subtree-of-another-tree/) | Algorithms | [TypeScript](./problems/algorithms/subtreeOfAnotherTree/SubtreeOfAnotherTree.ts) | Easy | | ... | ... | ... | ... | ... | In this table: diff --git a/problems/algorithms/subtreeOfAnotherTree/SubtreeOfAnotherTree.test.ts b/problems/algorithms/subtreeOfAnotherTree/SubtreeOfAnotherTree.test.ts new file mode 100644 index 0000000..4c566cc --- /dev/null +++ b/problems/algorithms/subtreeOfAnotherTree/SubtreeOfAnotherTree.test.ts @@ -0,0 +1,50 @@ +// Source : https://leetcode.com/problems/subtree-of-another-tree/ +// Author : Francisco Tomas +// Date : 2023-12-01 + +import { NodeTree, isSubtree } from "./SubtreeOfAnotherTree"; + +describe("subtree of another tree", () => { + test("smaller binary tree", () => { + const result: boolean = isSubtree( + new NodeTree( + 3, + new NodeTree( + 4, + new NodeTree(1, null, null), + new NodeTree(2, null, null), + ), + new NodeTree(5, null, null), + ), + new NodeTree(4, new NodeTree(1, null, null), new NodeTree(2, null, null)), + ); + + expect(result).toBe(true); + }); + + test("slightly larger binary tree", () => { + const result: boolean = isSubtree( + new NodeTree( + 3, + new NodeTree( + 4, + new NodeTree(1, null, null), + new NodeTree(2, new NodeTree(0, null, null), null), + ), + new NodeTree(5, null, null), + ), + new NodeTree(4, new NodeTree(1, null, null), new NodeTree(2, null, null)), + ); + + expect(result).toBe(false); + }); + + test("repeating node values", () => { + const result: boolean = isSubtree( + new NodeTree(1, new NodeTree(1, null, null), null), + new NodeTree(1, null, null), + ); + + expect(result).toBe(true); + }); +}); diff --git a/problems/algorithms/subtreeOfAnotherTree/SubtreeOfAnotherTree.ts b/problems/algorithms/subtreeOfAnotherTree/SubtreeOfAnotherTree.ts new file mode 100644 index 0000000..7457896 --- /dev/null +++ b/problems/algorithms/subtreeOfAnotherTree/SubtreeOfAnotherTree.ts @@ -0,0 +1,100 @@ +// Source : https://leetcode.com/problems/subtree-of-another-tree/ +// Author : Francisco Tomas +// Date : 2023-12-01 + +/***************************************************************************************************** + * + * Given the roots of two binary trees root and subRoot, return true if there is a subtree of root + * with the same structure and node values of subRoot and false otherwise. + * + * A subtree of a binary tree tree is a tree that consists of a node in tree and all of this node's + * descendants. The tree tree could also be considered as a subtree of itself. + * + * Example 1: + * + * Input: root = [3,4,5,1,2], subRoot = [4,1,2] + * Output: true + * + * Example 2: + * + * Input: root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2] + * Output: false + * + * Constraints: + * + * The number of nodes in the root tree is in the range [1, 2000]. + * The number of nodes in the subRoot tree is in the range [1, 1000]. + * -10^4 <= root.val <= 10^4 + * -10^4 <= subRoot.val <= 10^4 + ******************************************************************************************************/ + +type BT = NodeTree | null; + +export class NodeTree { + val: number; + left: BT; + right: BT; + constructor(val?: number, left?: BT, right?: BT) { + this.val = val ?? 0; + this.left = left === undefined ? null : left; + this.right = right === undefined ? null : right; + } +} + +/** + * (BT) (BT) -> boolean + * given the roots of two binary trees, root and subRoot, return true if there is a subtree of root + * with the same structure and node values of subRoot and false otherwise + * NOTES: - A subtree of a binary tree, tree, is a tree that consists of a node in tree and all of this node's descendants + * - The tree, tree, could also be considered as a subtree of itself + + * Stub: + function isSubtree(root: BT, subRoot: BT): boolean {return false} + + * Tests: + * I: root = [3,4,5,1,2], subRoot = [4,1,2] -> O: true + * I: root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2] -> O: false + * I: root = [1,1], subRoot = [1] -> O: true + + * Constraints: + * - The number of nodes in the root tree is in the range [1, 2000]. + * - The number of nodes in the subRoot tree is in the range [1, 1000]. + * - -10^4 <= root.val <= 10^4 + * - -10^4 <= subRoot.val <= 10^4 + */ + +/** + * Time Complexity: O(m * n), where m is the number of nodes in root and n the number of nodes in subRoot + * Space Complexity: O(h), where h is the height of root + + * Runtime: 73ms (74.58%) + * Memory: 49.68MB (79.57%) + */ +export function isSubtree(root: BT, subRoot: BT): boolean { + if (root === null) { + return false; + } else if (isEqual(root, subRoot)) { + return true; + } else { + return isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); + } +} + +/** + * Time Complexity: O(min(m, n)), where m is the number of nodes in root1 and n is the number of nodes in root2 + * the function compares corresponding nodes until one of the trees is exhausted + * Space Complexity: O(min(h, l)), where h is the height of root1 and l is the height of root2 + */ +function isEqual(root1: BT, root2: BT): boolean { + if (root1 === null && root2 === null) { + return true; + } else if (root1 === null || root2 === null) { + return false; + } else { + return ( + root1.val === root2.val && + isEqual(root1.left, root2.left) && + isEqual(root1.right, root2.right) + ); + } +}