diff --git a/construct-binary-tree-from-preorder-and-inorder-traversal/whewchews.ts b/construct-binary-tree-from-preorder-and-inorder-traversal/whewchews.ts new file mode 100644 index 000000000..4e87a4269 --- /dev/null +++ b/construct-binary-tree-from-preorder-and-inorder-traversal/whewchews.ts @@ -0,0 +1,49 @@ +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; + } +} + +/** + * preorder: [root, left, right] + * inorder: [left, root, right] + * preorder의 첫번째 값은 root이다. (1. 현재 root 찾기) + * 모든 node의 val는 unique하기 때문에 이 값을 기준으로 inorder에서 root의 위치를 찾을 수 있다. + * + * inorder에서 root의 위치를 찾으면, root를 기준으로 왼쪽은 left subtree, 오른쪽은 right subtree이다. (2. left subtree, right subtree 구분) + * inorder: [...left, root, ...right] + * root값은 이미 찾았기 때문에 shift로 제거한다. + * + * 남은 preorder에서 첫번째 값은 left subtree의 root이다. (3. left subtree 구성) + * preorder에서 하나씩 shift하면서 왼쪽 트리를 먼저 구성한다. + * preorder에서 첫번째 값이 왼쪽 subtree의 root이다. (1. 현재 root 찾기) + * inorder에서 root의 위치를 찾아서 왼쪽 subtree를 구성한다. (2. left subtree, right subtree 구분) (3. left subtree 구성) + * root 기준 왼쪽 subtree 구성이 끝나면 오른쪽 subtree를 구성한다. + * 위 과정을 재귀적으로 반복하면, 전체 트리를 구성할 수 있다. (1-3 과정 반복) + */ +function buildTree(preorder: number[], inorder: number[]): TreeNode | null { + // build 함수가 각 노드마다 호출됨(N) * 각 노드마다 shift, indexOf 수행(N) = O(N^2) + function build(preorder, inorder) { + if (inorder.length) { + // TC: O(N) + const idx = inorder.indexOf(preorder.shift()); + const root = new TreeNode(inorder[idx]); + + root.left = build(preorder, inorder.slice(0, idx)); + root.right = build(preorder, inorder.slice(idx + 1)); + + return root; + } + return null; + } + + return build(preorder, inorder); +} + +// TC: O(N^2) +// SC: O(N^2) diff --git a/counting-bits/whewchews.ts b/counting-bits/whewchews.ts new file mode 100644 index 000000000..b243840f7 --- /dev/null +++ b/counting-bits/whewchews.ts @@ -0,0 +1,19 @@ +function countBits(n: number): number[] { + // SC: O(N) + const ans = Array(n + 1).fill(0); + // TC: O(N) + for (let i = 1; i <= n; i++) { + let k = i; + + // TC: O(log N) + while (k > 0) { + ans[i] += k % 2; + k = Math.floor(k / 2); + } + } + + return ans; +} + +// TC: O(N log N) +// SC: O(N) diff --git a/decode-ways/whewchews.ts b/decode-ways/whewchews.ts new file mode 100644 index 000000000..77475c769 --- /dev/null +++ b/decode-ways/whewchews.ts @@ -0,0 +1,33 @@ +function numDecodings(s: string): number { + // SC: O(N) + const memo: { [key: number]: number } = { [s.length]: 1 }; + + // TC: O(N) + const dfs = (start: number): number => { + if (start in memo) { + return memo[start]; + } + + if (s[start] === "0") { + // 0으로 시작하는 경우 가능한 경우의 수가 없음 + memo[start] = 0; + } else if ( + start + 1 < s.length && + parseInt(s.substring(start, start + 2)) < 27 + ) { + // 다음에 오는 글자가 두글자 이상 있고, start start+1 두글자가 1~26 사이의 값인 경우 + memo[start] = dfs(start + 1) + dfs(start + 2); + } else { + // 1글자만 남은 경우 or 첫 두글자가 27보다 큰 경우 + memo[start] = dfs(start + 1); + } + + return memo[start]; + }; + + // SC: 재귀호출 O(N) + return dfs(0); +} + +// TC: O(N) +// SC: O(N) diff --git a/valid-anagram/whewchews.ts b/valid-anagram/whewchews.ts new file mode 100644 index 000000000..9751a2a25 --- /dev/null +++ b/valid-anagram/whewchews.ts @@ -0,0 +1,21 @@ +function isAnagram(s: string, t: string): boolean { + // TC: O(1) + if (s.length !== t.length) return false; + + // SC: O(N) + const count: { [key: string]: number } = {}; + + // TC: O(N) + for (let i = 0; i <= s.length - 1; i++) { + const sChar = s[i]; + const tChar = t[i]; + count[sChar] = (count[sChar] ?? 0) + 1; + count[tChar] = (count[tChar] ?? 0) - 1; + } + + // TC: O(N) + return Object.values(count).every((v) => v === 0); +} + +// TC: O(N) +// SC: O(N)