diff --git a/linked-list-cycle/soobing.ts b/linked-list-cycle/soobing.ts new file mode 100644 index 000000000..d363c846f --- /dev/null +++ b/linked-list-cycle/soobing.ts @@ -0,0 +1,52 @@ +/** + * 문제 설명 + * - 링크드리스트 내에 cycle이 존재하는지 확인하는 문제 + * + * 아이디어 + * - 링크드리스트를 끝까지 순회하면서 방문한 노드를 저장하고, 방문한 노드가 존재하면 cycle이 존재하는 것으로 판단 + * - 시간복잡도: O(n), 공간복잡도 O(n) + * + */ + +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; + } +} + +function hasCycle(head: ListNode | null): boolean { + const visited = new Set(); + + while (head) { + if (visited.has(head)) { + return true; + } else { + visited.add(head); + head = head.next; + } + } + return false; +} + +/** + * 공간복잡도 O(1) 로도 풀 수 있음. + */ + +// function hasCycle(head: ListNode | null): boolean { +// let slow = head; +// let fast = head; + +// while (fast && fast.next) { +// slow = slow!.next; +// fast = fast.next.next!; + +// if (slow === fast) { +// return true; +// } +// } + +// return false; +// } diff --git a/maximum-product-subarray/soobing.ts b/maximum-product-subarray/soobing.ts new file mode 100644 index 000000000..c70cfa2ad --- /dev/null +++ b/maximum-product-subarray/soobing.ts @@ -0,0 +1,22 @@ +/** + * 문제 설명 + * - 배열에서 연속된 부분 배열의 곱이 가장 큰 값을 찾는 문제 + * + * 아이디어 + * - 1) 브루트포스 O(n^2) + * - 2) DP 최적화 O(n) + * - 매 index마다, 현재까지 max 곱, min 곱을 찾고 최대값을 갱신 + */ +function maxProduct(nums: number[]): number { + let maxSoFar = nums[0]; + let max = nums[0]; + let min = nums[0]; + + for (let i = 1; i < nums.length; i++) { + const candidate = [nums[i], max * nums[i], min * nums[i]]; + max = Math.max(...candidate); + min = Math.min(...candidate); + maxSoFar = Math.max(maxSoFar, max); + } + return maxSoFar; +} diff --git a/minimum-window-substring/soobing.ts b/minimum-window-substring/soobing.ts new file mode 100644 index 000000000..ede9f77a5 --- /dev/null +++ b/minimum-window-substring/soobing.ts @@ -0,0 +1,54 @@ +/** + * 문제 설명 + * - 주어진 문자열 s에서 주어진 문자열 t의 모든 문자를 포함하는 최소 윈도우를 찾는 문제 + * + * 아이디어 + * - 슬라이딩 윈도우 + 해시맵(need, window)을 이용하여 풀이한다. + * - 오른쪽 포인터를 먼저 이동하고, 이미 모두 포함되어 있는 경우 왼쪽 포인터를 이동하여 최소 윈도우를 찾는다. + * + */ +function minWindow(s: string, t: string): string { + if (t.length > s.length) return ""; + + const need = new Map(); + const window = new Map(); + + for (const char of t) { + need.set(char, (need.get(char) || 0) + 1); + } + + let have = 0; + let needSize = need.size; + let res = [-1, -1]; + let resLen = Infinity; + + let left = 0; + + for (let right = 0; right < s.length; right++) { + const c = s[right]; + window.set(c, (window.get(c) || 0) + 1); + + if (need.has(c) && window.get(c) === need.get(c)) { + have++; + } + + while (have === needSize) { + const currentResLen = right - left + 1; + if (currentResLen < resLen) { + res = [left, right]; + resLen = currentResLen; + } + + const lChar = s[left]; + window.set(lChar, window.get(lChar)! - 1); + + if (need.has(lChar) && window.get(lChar)! < need.get(lChar)!) { + have--; + } + left++; + } + } + + const [start, end] = res; + return resLen === Infinity ? "" : s.slice(start, end + 1); +} diff --git a/pacific-atlantic-water-flow/soobing.ts b/pacific-atlantic-water-flow/soobing.ts new file mode 100644 index 000000000..96a9557f2 --- /dev/null +++ b/pacific-atlantic-water-flow/soobing.ts @@ -0,0 +1,64 @@ +/** + * 문제 설명 + * - 비가 내렸을 때, 태평양과 대서양 모두로 물이 흐를 수 있는 지점을 찾아 반환하는 문제입니다. + * 아이디어 + * 1) BFS/DFS + * - 각 바다에서 역방향으로 물이 도달할 수 있는 셀을 탐색한 후, 두 바다 모두에 도달 가능한 셀의 교집합 구하기 + * + */ + +function pacificAtlantic(heights: number[][]): number[][] { + const m = heights.length; + const n = heights[0].length; + + const pacific = Array.from({ length: m }, () => Array(n).fill(false)); + const atlantic = Array.from({ length: m }, () => Array(n).fill(false)); + + const directions = [ + [1, 0], + [-1, 0], + [0, 1], + [0, -1], + ]; + + function dfs(r: number, c: number, visited: boolean[][], prevHeight: number) { + if ( + r < 0 || + c < 0 || + r >= m || + c >= n || + visited[r][c] || + heights[r][c] < prevHeight + ) + return; + + visited[r][c] = true; + + for (const [dr, dc] of directions) { + dfs(r + dr, c + dc, visited, heights[r][c]); + } + } + + // 태평양 DFS + for (let i = 0; i < m; i++) { + dfs(i, 0, pacific, heights[i][0]); // 왼쪽 + dfs(i, n - 1, atlantic, heights[i][n - 1]); // 오른쪽 + } + + for (let j = 0; j < n; j++) { + dfs(0, j, pacific, heights[0][j]); // 위쪽 + dfs(m - 1, j, atlantic, heights[m - 1][j]); // 아래쪽 + } + + const result: number[][] = []; + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (pacific[i][j] && atlantic[i][j]) { + result.push([i, j]); + } + } + } + + return result; +} diff --git a/sum-of-two-integers/soobing.ts b/sum-of-two-integers/soobing.ts new file mode 100644 index 000000000..b6b865e27 --- /dev/null +++ b/sum-of-two-integers/soobing.ts @@ -0,0 +1,16 @@ +/** + * 문제 설명 + * - 두 정수의 합을 반환하는 문제 (비트 연산을 통해서) + * + * 아이디어 + * - 반올림은 AND(&) + 왼쪽 shift 1, 덧셈은 XOR(^) 연산을 통해서 한다. + * - 반올림이 0이 될 때까지 반복한다. ⭐️ + */ +function getSum(a: number, b: number): number { + while (b !== 0) { + const carry = (a & b) << 1; + a = a ^ b; + b = carry; + } + return a; +}