From 6cbb599dd9a555970aa1abf980644664b911d734 Mon Sep 17 00:00:00 2001 From: soobing Date: Mon, 19 May 2025 22:16:40 +0900 Subject: [PATCH 1/5] feat(soobing): week8 > reverse-bits --- reverse-bits/soobing.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 reverse-bits/soobing.ts diff --git a/reverse-bits/soobing.ts b/reverse-bits/soobing.ts new file mode 100644 index 000000000..db85ee159 --- /dev/null +++ b/reverse-bits/soobing.ts @@ -0,0 +1,22 @@ +/** + * + * 문제 설명 + * - 32비트 unsigned 정수의 비트 순서를 뒤집어서 다시 정수로 반환하는 문제 + * + * 아이디어 + * - 비트 연산을 이해하고, O(1)알아가는데 의의를 두면 좋을 것 같음. + * + * 비트 연산 + * >>>, >>, <<, &, | + * - signed, unsigned 연산 + */ +function reverseBits(n: number): number { + let result = 0; + for (let i = 0; i < 32; i++) { + result <<= 1; + result |= n & 1; + n >>>= 1; + } + + return result >>> 0; +} From 2ec11554202f25bb3871af1b87f22e147e125136 Mon Sep 17 00:00:00 2001 From: soobing Date: Tue, 20 May 2025 23:09:30 +0900 Subject: [PATCH 2/5] feat(soobing): week8 > longest-repeating-character-replacement --- .../soobing.ts | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 longest-repeating-character-replacement/soobing.ts diff --git a/longest-repeating-character-replacement/soobing.ts b/longest-repeating-character-replacement/soobing.ts new file mode 100644 index 000000000..e79e89123 --- /dev/null +++ b/longest-repeating-character-replacement/soobing.ts @@ -0,0 +1,34 @@ +/** + * 문제 설명 + * - k번 문자 대체를 통해 가장 길게 반복되는 문자열 찾기 + * + * 아이디어 + * 1) Sliding Window 활용 + * - 투포인터 알고리즘을 활용하여 현재 윈도우 내에서 k번 문자 대체가 가능한지 체크하고, + * 윈도우 크기를 조절하면서 최대 길이를 찾는다. + * + * 시간 복잡도 + * - O(n) + * - 문자열을 한번 순회하면서 윈도우 크기를 조절하기 때문에 O(n)의 시간 복잡도를 가진다. + * + * 공간 복잡도 + * - O(1) + */ + +function characterReplacement(s: string, k: number): number { + let start = 0; + const map: Record = {}; + let maxLength = 0; + let maxCount = 0; + for (let end = 0; end < s.length; end++) { + map[s[end]] = (map[s[end]] || 0) + 1; + maxCount = Math.max(maxCount, map[s[end]]); + while (end - start + 1 - maxCount > k) { + map[s[start]]--; + start++; + } + + maxLength = Math.max(end - start + 1, maxLength); + } + return maxLength; +} From b85d795f2ea0927aede9e366e83e1acb7d1cfbba Mon Sep 17 00:00:00 2001 From: soobing Date: Wed, 21 May 2025 23:18:06 +0900 Subject: [PATCH 3/5] feat(soobing): week8 > clone-graph --- clone-graph/soobing.ts | 84 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 clone-graph/soobing.ts diff --git a/clone-graph/soobing.ts b/clone-graph/soobing.ts new file mode 100644 index 000000000..901fba449 --- /dev/null +++ b/clone-graph/soobing.ts @@ -0,0 +1,84 @@ +/** + * 문제 설명 + * - 그래프를 탐색하면서 완전 복제하는 문제 + * + * 아이디어 + * 1) 그래프 탐색 알고리즘 + * - 그래프 복사는 네트워크 유형에 해당하므로 bfs 혹은 dfs로 풀이한다. + */ + +/** + * Definition for _Node. + * class _Node { + * val: number + * neighbors: _Node[] + * + * constructor(val?: number, neighbors?: _Node[]) { + * this.val = (val===undefined ? 0 : val) + * this.neighbors = (neighbors===undefined ? [] : neighbors) + * } + * } + * + */ + +class _Node { + val: number; + neighbors: _Node[]; + + constructor(val?: number, neighbors?: _Node[]) { + this.val = val === undefined ? 0 : val; + this.neighbors = neighbors === undefined ? [] : neighbors; + } +} + +function cloneGraph(node: _Node | null): _Node | null { + if (node === null) return null; + + const visited = new Map<_Node, _Node>(); + + function dfs(cur: _Node): _Node { + if (visited.has(cur)) { + return visited.get(cur)!; + } + + const cloned = new _Node(cur.val); + visited.set(cur, cloned); + + for (const neighbor of cur.neighbors) { + cloned.neighbors.push(dfs(neighbor)); + } + + return cloned; + } + + return dfs(node); +} + +/** + * BFS 풀이 +function cloneGraph(node: _Node | null): _Node | null { + if(!node) return null; + + const visited = new Map<_Node, _Node>(); + + const cloneStart = new _Node(node.val); + visited.set(node, cloneStart); + + const queue: _Node[] = [node]; + + while(queue.length > 0) { + const cur = queue.shift(); + const curClone = visited.get(cur); + + for(const neighbor of cur.neighbors) { + if(!visited.get(neighbor)) { + visited.set(neighbor, new _Node(neighbor.val)); + queue.push(neighbor); + } + + curClone.neighbors.push(visited.get(neighbor)); + } + } + return cloneStart; +}; + */ From b8a8823b98df668be2c043f8194052e98a62da65 Mon Sep 17 00:00:00 2001 From: soobing Date: Sat, 24 May 2025 23:00:17 +0900 Subject: [PATCH 4/5] feat(soobing): week8 > palindromic-substrings --- palindromic-substrings/soobing.ts | 35 +++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 palindromic-substrings/soobing.ts diff --git a/palindromic-substrings/soobing.ts b/palindromic-substrings/soobing.ts new file mode 100644 index 000000000..ea5a6739f --- /dev/null +++ b/palindromic-substrings/soobing.ts @@ -0,0 +1,35 @@ +/** + * 문제 설명 + * - 주어진 문자열 s의 모든 부분 문자열 중 팰린드롬인 문자열의 개수를 반환 + * + * 아이디어 + * 1) 1. Brute Force O(n^3) + * 2) 투포인터 O(n^2) + * - 짝수, 홀수 두 가지 경우로 나누어 탐색 + * - 순회하면서 각 항목을 중심으로 좌우로 확장하며 팰린드롬인지 확인 + * 3) DP O(n^2) + * - dp[i][j]를 만들어서 s[i..j]가 팰린드롬인지 저장 -> 다음번에 해보기 + */ +function countSubstrings(s: string): number { + let result = 0; + + for (let i = 0; i < s.length; i++) { + let left = i; + let right = i; + + while (left >= 0 && right < s.length && s[left] === s[right]) { + result++; + left--; + right++; + } + + left = i; + right = i + 1; + while (left >= 0 && right < s.length && s[left] === s[right]) { + result++; + left--; + right++; + } + } + return result; +} From 7409de1169de17e86773461418d57182c0ec608c Mon Sep 17 00:00:00 2001 From: soobing Date: Sat, 24 May 2025 23:46:39 +0900 Subject: [PATCH 5/5] feat(soobing): week8 > longest-common-subsequence --- longest-common-subsequence/soobing.ts | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 longest-common-subsequence/soobing.ts diff --git a/longest-common-subsequence/soobing.ts b/longest-common-subsequence/soobing.ts new file mode 100644 index 000000000..13690d2cb --- /dev/null +++ b/longest-common-subsequence/soobing.ts @@ -0,0 +1,28 @@ +/** + * 문제 설명 + * - 두 문자열의 가장 긴 공통 부분 문자열의 길이를 반환 + * - 대표적인 DP 문제 + * + * 아이디어 + * 1) 브루투포스 O(n^2) + * 2) DP O(n^2) + * - dp[i][j]를 만들어서 text1[i]와 text2[j]가 같은 경우 dp[i][j] = dp[i-1][j-1] + 1 + * - 다른 경우 dp[i][j] = Math.max(dp[i-1][j], dp[i][j-1]) + */ + +function longestCommonSubsequence(text1: string, text2: string): number { + const dp = Array.from({ length: text1.length + 1 }, () => + Array(text2.length + 1).fill(0) + ); + + for (let i = 1; i <= text1.length; i++) { + for (let j = 1; j <= text2.length; j++) { + if (text1[i - 1] === text2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]); + } + } + } + return dp[text1.length][text2.length]; +}