diff --git a/binary-tree-level-order-traversal/soobing.ts b/binary-tree-level-order-traversal/soobing.ts new file mode 100644 index 000000000..e4def6ddd --- /dev/null +++ b/binary-tree-level-order-traversal/soobing.ts @@ -0,0 +1,43 @@ +/** + * 문제 설명 + * - 이진 트리의 레벨 순서 순회 문제 + * + * 아이디어 + * 1) BFS 레벨 순서별로 큐에 넣어서 탐색하며 결과를 반환 + * + */ +/** + * Definition for a binary tree node. + * 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) + * } + * } + */ + +function levelOrder(root: TreeNode | null): number[][] { + if (!root) return []; + + const queue: TreeNode[] = [root]; + const result: number[][] = []; + + while (queue.length) { + const levelSize = queue.length; + const currentLevel: number[] = []; + for (let i = 0; i < levelSize; i++) { + const node = queue.shift()!; + currentLevel.push(node.val); + + if (node.left) queue.push(node.left); + if (node.right) queue.push(node.right); + } + + result.push(currentLevel); + } + return result; +} diff --git a/counting-bits/soobing.ts b/counting-bits/soobing.ts new file mode 100644 index 000000000..e9fbb62e5 --- /dev/null +++ b/counting-bits/soobing.ts @@ -0,0 +1,15 @@ +/** + * 문제 설명 + * - 0부터 n까지의 모든 수에 대해 이진수에서 1의 개수를 세는 함수를 작성하라. + * + * 아이디어 + * 1) DP + 비트연산 + * - ans[i] = ans[i >> 1] + (i & 1) + */ +function countBits(n: number): number[] { + const ans = Array(n + 1).fill(0); + for (let i = 1; i <= n; i++) { + ans[i] = ans[i >> 1] + (i & 1); + } + return ans; +} diff --git a/house-robber/soobing.ts b/house-robber/soobing.ts new file mode 100644 index 000000000..ad17c73f3 --- /dev/null +++ b/house-robber/soobing.ts @@ -0,0 +1,34 @@ +/** + * 문제 설명 + * - 주어진 배열의 시작과 끝이 연결되어 있는 원형이라고 할 경우에, 이웃하는 집은 털 수 없고 최대로 털 수 있는 돈을 구하는 문제 + * + * 아이디어 + * 1) 동적 계획법(Dynamic Programming) 활용 + * - 원형 구조이므로 첫번째 집과 마지막집은 동시에 털 수 없음 + * - 따라서 두 가지 경우로 나누어 계산하고, 두 결과 중 더 큰 값을 반환 + * 2) 선형 배열에 대한 최대 금액 계산 + * - 매 순회마다 현재 집을 털 경우(prev2 + num)와 털지 않을 경우(prev1) 중 큰 값을 선택 + * - 최종적으로 prev1에 최대값이 저장 + */ +function robLinear(nums: number[]) { + let prev1 = 0; + let prev2 = 0; + + for (const num of nums) { + const temp = prev1; + prev1 = Math.max(prev2 + num, prev1); + prev2 = temp; + } + + return prev1; +} + +function rob(nums: number[]): number { + if (nums.length === 1) return nums[0]; + if (nums.length === 2) return Math.max(nums[0], nums[1]); + + const temp1 = robLinear(nums.slice(0, nums.length - 1)); + const temp2 = robLinear(nums.slice(1)); + + return Math.max(temp1, temp2); +} diff --git a/meeting-rooms-ii/soobing.ts b/meeting-rooms-ii/soobing.ts new file mode 100644 index 000000000..e168ca9fb --- /dev/null +++ b/meeting-rooms-ii/soobing.ts @@ -0,0 +1,37 @@ +/** + * 문제 설명 + * - 주어진 회의시간을 진행할 수 있는 최소의 회의시간 갯수 구하기 + * + * 아이디어 + * 1) minheap + greeday + * - 회의시간 시작시간으로 정렬(회의 일정을 시간 순으로 처리) + * - Heap에는 현재 사용 중인 회의실의 종료 시간들만 저장 + * - 회의 시작시간이 끝시간보다 같거나 크면 회의실 쓸수 있는 거니까 shift 해서 회의 꺼냄 + * - 회의시간 끝 시간을 힙에 넣고, 끝시간 오름차순으로 정렬(minheap) + * - 최종적으로 heap의 크기 = 필요한 회의실 개수 + */ + +type Interval = { start: number; end: number }; + +class Solution { + minMeetingRooms(intervals: Interval[]): number { + if (intervals.length === 0) return 0; + + intervals.sort((a, b) => a.start - b.start); + + const heap: number[] = []; + + for (const interval of intervals) { + const { start, end } = interval; + + if (heap.length > 0 && heap[0] <= start) { + heap.shift(); + } + + heap.push(end); + heap.sort((a, b) => a - b); + } + + return heap.length; + } +} diff --git a/word-search-ii/soobing.ts b/word-search-ii/soobing.ts new file mode 100644 index 000000000..e8f573a00 --- /dev/null +++ b/word-search-ii/soobing.ts @@ -0,0 +1,83 @@ +/** + * 문제 설명 + * - 2차원 배열에서 주어진 단어들을 찾는 문제 + * + * 아이디어 + * 1) Trie 자료구조 + DFS & Backtracking (👀어려웠음..다시 풀어보기) + * - 주어진 단어들을 Trie 자료구조로 변환 + * - 2차원 배열을 순회하면서 Trie 자료구조를 사용하여 단어를 찾음 + * - 찾은 단어는 배열에 추가 + */ +class TrieNode { + private nodes = new Map(); + word: string | null = null; + + add(word: string) { + let currentNode = this as TrieNode; + for (const char of word) { + if (!currentNode.nodes.has(char)) { + currentNode.nodes.set(char, new TrieNode()); + } + currentNode = currentNode.nodes.get(char)!; + } + currentNode.word = word; + } + + getNode(char: string) { + return this.nodes.get(char); + } + + hasChar(char: string) { + return this.nodes.has(char); + } +} + +function search( + m: number, + n: number, + board: string[][], + node: TrieNode, + result: string[] +) { + const M = board.length; + const N = board[0].length; + if (m < 0 || m >= M || n < 0 || n >= N) return; + + const currentChar = board[m][n]; + if (currentChar === "#" || !node.hasChar(currentChar)) return; + + node = node.getNode(currentChar)!; + + if (node.word) { + result.push(node.word); + node.word = null; + } + + board[m][n] = "#"; + + search(m + 1, n, board, node, result); + search(m - 1, n, board, node, result); + search(m, n + 1, board, node, result); + search(m, n - 1, board, node, result); + + board[m][n] = currentChar; +} + +function findWords(board: string[][], words: string[]): string[] { + const root = new TrieNode(); + for (const word of words) { + root.add(word); + } + + const result: string[] = []; + const M = board.length; + const N = board[0].length; + + for (let i = 0; i < M; i++) { + for (let j = 0; j < N; j++) { + search(i, j, board, root, result); + } + } + + return result; +}