diff --git a/merge-intervals/HC-kang.ts b/merge-intervals/HC-kang.ts new file mode 100644 index 000000000..08b118c61 --- /dev/null +++ b/merge-intervals/HC-kang.ts @@ -0,0 +1,24 @@ +/** + * https://leetcode.com/problems/merge-intervals + * T.C. O(n logn) + * S.C. O(n) + */ +function merge(intervals: number[][]): number[][] { + intervals.sort((a, b) => a[0] - b[0]); // T.C. O(n logn) + + const result = [intervals[0]]; // S.C. O(n) + + // T.C. O(n) + for (let i = 1; i < intervals.length; i++) { + const last = result[result.length - 1]; + const current = intervals[i]; + + if (last[1] >= current[0]) { + last[1] = Math.max(last[1], current[1]); + } else { + result.push(current); + } + } + + return result; +} diff --git a/number-of-connected-components-in-an-undirected-graph/HC-kang.ts b/number-of-connected-components-in-an-undirected-graph/HC-kang.ts new file mode 100644 index 000000000..511158838 --- /dev/null +++ b/number-of-connected-components-in-an-undirected-graph/HC-kang.ts @@ -0,0 +1,71 @@ +/** + * https://leetcode.com/problems/number-of-connected-components-in-an-undirected-graph + * T.C. O(V + E) + * S.C. O(V + E) + */ +function countComponents(n: number, edges: number[][]): number { + const graph = new Map(); + + for (let i = 0; i < n; i++) { + graph.set(i, []); + } + + for (const [u, v] of edges) { + graph.get(u)!.push(v); + graph.get(v)!.push(u); + } + + function dfs(node: number) { + visited.add(node); + + for (const neighbor of graph.get(node)!) { + if (!visited.has(neighbor)) { + dfs(neighbor); + } + } + } + + const visited = new Set(); + + let components = 0; + + for (let i = 0; i < n; i++) { + if (!visited.has(i)) { + components++; + dfs(i); + } + } + + return components; +} + +/** + * Using Union Find + * T.C. O(V + E) + * + */ +function countComponents(n: number, edges: number[][]): number { + const parent = Array.from({ length: n }, (_, i) => i); + + // find and compress path + function find(x: number): number { + if (parent[x] !== x) { + parent[x] = find(parent[x]); + } + return parent[x]; + } + + // union two sets and check if they have the same root + function union(x: number, y: number): boolean { + const rootX = find(x); + const rootY = find(y); + parent[rootX] = rootY; + return true; + } + + for (const [x, y] of edges) { + union(x, y); + } + + return new Set(parent.map(find)).size; +} diff --git a/remove-nth-node-from-end-of-list/HC-kang.ts b/remove-nth-node-from-end-of-list/HC-kang.ts new file mode 100644 index 000000000..53945c5b2 --- /dev/null +++ b/remove-nth-node-from-end-of-list/HC-kang.ts @@ -0,0 +1,33 @@ +class ListNode { + val: number; + next: ListNode | null; + constructor(val?: number, next?: ListNode | null) { + this.val = val === undefined ? 0 : val; + this.next = next === undefined ? null : next; + } +} + +/** + * https://leetcode.com/problems/remove-nth-node-from-end-of-list + * T.C. O(N) + * S.C. O(1) + */ +function removeNthFromEnd(head: ListNode | null, n: number): ListNode | null { + let first = head; + let second = head; + + for (let i = 0; i < n; i++) + first = first!.next; + + if (!first) + return head!.next; + + while (first.next) { + first = first.next; + second = second!.next; + } + + second!.next = second!.next!.next; + + return head; +} diff --git a/same-tree/HC-kang.ts b/same-tree/HC-kang.ts new file mode 100644 index 000000000..5d2a8ed81 --- /dev/null +++ b/same-tree/HC-kang.ts @@ -0,0 +1,41 @@ +class TreeNode { + val: number; + left: TreeNode | null; + right: TreeNode | null; + constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + this.val = val === undefined ? 0 : val; + this.left = left === undefined ? null : left; + this.right = right === undefined ? null : right; + } +} + +/** + * https://leetcode.com/problems/same-tree/description/ + * T.C. O(n) + * S.C. O(n) + */ +function isSameTree(p: TreeNode | null, q: TreeNode | null): boolean { + if (p === null && q === null) return true; + if (p === null || q === null) return false; + if (p.val !== q.val) return false; + return isSameTree(p.left, q.left) && isSameTree(p.right, q.right); +} + +/** + * T.C. O(n) + * S.C. O(n) + */ +function isSameTree(p: TreeNode | null, q: TreeNode | null): boolean { + const stack: [TreeNode | null, TreeNode | null][] = [[p, q]]; + + while (stack.length) { + const [node1, node2] = stack.pop()!; + if (node1 === null && node2 === null) continue; + if (node1 === null || node2 === null) return false; + if (node1.val !== node2.val) return false; + stack.push([node1.left, node2.left]); + stack.push([node1.right, node2.right]); + } + + return true; +} diff --git a/serialize-and-deserialize-binary-tree/HC-kang.ts b/serialize-and-deserialize-binary-tree/HC-kang.ts new file mode 100644 index 000000000..07c928e57 --- /dev/null +++ b/serialize-and-deserialize-binary-tree/HC-kang.ts @@ -0,0 +1,51 @@ +class TreeNode { + val: number; + left: TreeNode | null; + right: TreeNode | null; + constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) { + this.val = val === undefined ? 0 : val; + this.left = left === undefined ? null : left; + this.right = right === undefined ? null : right; + } +} + +/** + * https://leetcode.com/problems/serialize-and-deserialize-binary-tree + * T.C. O(n) + * S.C. O(n) + */ +function serialize(root: TreeNode | null): string { + return JSON.stringify(root); +} + +function deserialize(data: string): TreeNode | null { + return JSON.parse(data); +} + +/** + * Recursive + * T.C. O(n) + * S.C. O(n) + */ +function serialize(root: TreeNode | null): string { + return root + ? `${root.val},${serialize(root.left)},${serialize(root.right)}` + : 'null'; +} + +function deserialize(data: string): TreeNode | null { + const values = data.split(','); + let index = 0; + + function dfs(): TreeNode | null { + const val = values[index++]; + if (val === 'null') return null; + + const node = new TreeNode(parseInt(val)); + node.left = dfs(); + node.right = dfs(); + return node; + } + + return dfs(); +}