diff --git a/longest-palindromic-substring/Jeehay28.js b/longest-palindromic-substring/Jeehay28.js new file mode 100644 index 000000000..187524859 --- /dev/null +++ b/longest-palindromic-substring/Jeehay28.js @@ -0,0 +1,76 @@ +// ✅ Time Complexity: O(n^2), where n represents the length of the input string s +// ✅ Space Complexity: O(n) + +/** + * @param {string} s + * @return {string} + */ +var longestPalindrome = function (s) { + let max_left = 0, + max_right = 0; + + for (let i = 0; i < s.length; i++) { + // Odd-length palindromes + let left = i, + right = i; + + while (left >= 0 && right < s.length && s[left] === s[right]) { + if (max_right - max_left < right - left) { + max_right = right; + max_left = left; + } + left -= 1; + right += 1; + } + + // Even-length palindromes + left = i; + right = i + 1; + + while (left >= 0 && right < s.length && s[left] === s[right]) { + if (max_right - max_left < right - left) { + max_right = right; + max_left = left; + } + left -= 1; + right += 1; + } + } + + return s.slice(max_left, max_right + 1); +}; + +// ✅ Time Complexity: O(n^3), where n represents the length of the input string s +// ✅ Space Complexity: O(n) + +/** + * @param {string} s + * @return {string} + */ +// var longestPalindrome = function (s) { +// const isPalindromic = (left, right) => { +// while (left < right) { +// if (s[left] !== s[right]) { +// return false; +// } +// left += 1; +// right -= 1; +// } + +// return true; +// }; + +// let max_left = 0, +// max_right = 0; +// for (let l = 0; l < s.length; l++) { +// for (let r = 0; r < s.length; r++) { +// if (isPalindromic(l, r) && max_right - max_left < r - l) { +// max_left = l; +// max_right = r; +// } +// } +// } + +// return s.slice(max_left, max_right + 1); +// }; + diff --git a/subtree-of-another-tree/Jeehay28.js b/subtree-of-another-tree/Jeehay28.js new file mode 100644 index 000000000..25e13714a --- /dev/null +++ b/subtree-of-another-tree/Jeehay28.js @@ -0,0 +1,76 @@ +// ✅ 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. +// ✅ Space Complexity: O(m + n) + +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {TreeNode} subRoot + * @return {boolean} + */ +var isSubtree = function (root, subRoot) { + // Helper function: Serializes a tree into a string representation in a pre-order fashion + // by visiting the node first, then left and right subtrees. This ensures each node is uniquely + // represented with its value, and the structure is captured recursively. + const serialize = (node) => { + if (!node) return "#"; // Use "#" to represent null nodes, ensuring we capture structure. + return `(${node.val},${serialize(node.left)},${serialize(node.right)})`; // Recursively serialize left and right children. + }; + + const serializedRoot = serialize(root); // O(m) for serializing root. + const serializedSubRoot = serialize(subRoot); // O(n) for serializing subRoot. + + return serializedRoot.includes(serializedSubRoot); // O(m * n) for the substring search. +}; + + + +// ✅ Time Complexity: O(m * n), where m is the number of nodes in root and n is the number of nodes in subRoot. +// ✅ Space Complexity: O(m + n), due to the recursion stack for both isSubtree and isSameTree. + +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {TreeNode} subRoot + * @return {boolean} + */ +// var isSubtree = function (root, subRoot) { +// // Base case: if root is null, subRoot can't be a subtree +// if (!root) return false; + +// // Helper function to check if two trees are identical +// const isSameTree = (node1, node2) => { +// if (!node1 && !node2) return true; // Both are null, they are identical +// if (!node1 || !node2) return false; // One is null, other is not, they are not identical + +// if (node1.val !== node2.val) return false; // Values don't match, not identical + +// // Recursively check both left and right subtrees +// return ( +// isSameTree(node1.left, node2.left) && isSameTree(node1.right, node2.right) +// ); +// }; + +// // If the current node of root is identical to subRoot, return true +// if (isSameTree(root, subRoot)) return true; + +// // isSubtree is true if subRoot exists as a subtree in either the left or right side of root. +// // It checks both sides recursively until it finds a match, and if found, returns true. +// // If it doesn't find a match in either subtree, it will return false. +// return isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); +// }; + + diff --git a/validate-binary-search-tree/Jeehay28.js b/validate-binary-search-tree/Jeehay28.js new file mode 100644 index 000000000..5d691a2f6 --- /dev/null +++ b/validate-binary-search-tree/Jeehay28.js @@ -0,0 +1,29 @@ +// ✅ Time Complexity: O(N), where N is the number of nodes in the tree. +// ✅ Space Complexity: O(N) + +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {boolean} + */ +var isValidBST = function (root) { + // Helper function to check BST validity + const dfs = (node, low, high) => { + // Base case: Empty subtree is valid + if (!node) return true; + + if (!(low < node.val && node.val < high)) return false; + + return dfs(node.left, low, node.val) && dfs(node.right, node.val, high); + }; + + return dfs(root, -Infinity, Infinity); +}; +