diff --git a/clone-graph/krokerdile.js b/clone-graph/krokerdile.js new file mode 100644 index 000000000..aaa71e400 --- /dev/null +++ b/clone-graph/krokerdile.js @@ -0,0 +1,27 @@ +/** + * @param {_Node} node + * @return {_Node} + */ +var cloneGraph = function(node) { + if (!node) return null; + + const visited = new Map(); // 원본 노드 -> 복제 노드 + + function dfs(curr) { + if (visited.has(curr)) { + return visited.get(curr); // 이미 복제한 경우 + } + + const copy = new _Node(curr.val); + visited.set(curr, copy); // 복제한 노드 저장 + + for (const neighbor of curr.neighbors) { + copy.neighbors.push(dfs(neighbor)); // 이웃도 재귀적으로 복사 + } + + return copy; + } + + return dfs(node); +}; + diff --git a/linked-list-cycle/krokerdile.js b/linked-list-cycle/krokerdile.js new file mode 100644 index 000000000..8e7fc3148 --- /dev/null +++ b/linked-list-cycle/krokerdile.js @@ -0,0 +1,23 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ + +/** + * @param {ListNode} head + * @return {boolean} + */ +var hasCycle = function(head) { + let list = new Set(); + while (head != null) { + if (list.has(head)) + return true; + list.add(head); + head = head.next; + } + + return false; +}; diff --git a/longest-common-subsequence/krokerdile.js b/longest-common-subsequence/krokerdile.js new file mode 100644 index 000000000..066c345de --- /dev/null +++ b/longest-common-subsequence/krokerdile.js @@ -0,0 +1,63 @@ +/** + * @param {string} text1 + * @param {string} text2 + * @return {number} + * + * 시간복잡도: O(m * n) + * - m = text1.length, n = text2.length + * - 2중 for문으로 dp 테이블 채우기 + * + * 공간복잡도: O(m * n) + * - dp 배열에 m * n 만큼의 공간 사용 + * - 최적화하려면 배열 2개로도 가능 + */ +var longestCommonSubsequence = function(text1, text2) { + let m = text1.length; + let n = text2.length; + + // 2차원 dp 배열 초기화 (m+1) x (n+1) + const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); + + // dp[i][j] = text1[0..i-1], text2[0..j-1] 까지의 LCS 길이 + for (let i = 1; i <= m; i++) { + for (let j = 1; j <= n; j++) { + if (text1[i - 1] === text2[j - 1]) { + // 문자가 같으면, 이전까지의 LCS + 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[m][n]; // 마지막 cell이 정답 +}; + +//실패한 dfs 코드 +/** + * @param {string} text1 + * @param {string} text2 + * @return {number} + */ +var longestCommonSubsequence = function(text1, text2) { + function dfs(i, j) { + // 종료 조건: 인덱스 범위를 벗어나면 0 + if (i === text1.length || j === text2.length) { + return 0; + } + + // 문자가 같으면, 다음 문자로 이동하며 길이 +1 + if (text1[i] === text2[j]) { + return 1 + dfs(i + 1, j + 1); + } + + // 문자가 다르면, 두 가지 갈래 중 최댓값을 선택 + return Math.max( + dfs(i + 1, j), // text1의 다음 문자로 + dfs(i, j + 1) // text2의 다음 문자로 + ); + } + + return dfs(0, 0); +}; diff --git a/palindromic-substrings/krokerdile.js b/palindromic-substrings/krokerdile.js new file mode 100644 index 000000000..ea73732fb --- /dev/null +++ b/palindromic-substrings/krokerdile.js @@ -0,0 +1,37 @@ +/** + * @param {string} s + * @return {number} + * + * 시간복잡도: O(n^2) + * - 각 문자(i)를 중심으로 확장 → 최대 n번 + * - 각 중심에서 양쪽으로 확장하면서 비교 → 최대 n번 + * → O(n) * O(n) = O(n^2) + * + * 공간복잡도: O(1) + * - 추가 공간 없이 count 변수와 index만 사용 + * - 문자열을 복사하거나 메모이제이션 하지 않음 + */ +var countSubstrings = function(s) { + let count = 0; + + // 전체 문자열을 순회하면서 각 위치를 팰린드롬 중심으로 잡음 + for (let i = 0; i < s.length; i++) { + // 홀수 길이 팰린드롬: ex. "aba" + helper(i, i); + + // 짝수 길이 팰린드롬: ex. "abba" + helper(i, i + 1); + } + + // 팰린드롬이 유지되는 동안 count 증가시키는 함수 + function helper(left, right) { + // 조건이 맞을 때마다 좌우로 확장 + while (left >= 0 && right < s.length && s[left] === s[right]) { + count++; // 유효한 팰린드롬 하나 발견 + left--; + right++; + } + } + + return count; +}; diff --git a/sum-of-two-integers/krokerdile.js b/sum-of-two-integers/krokerdile.js new file mode 100644 index 000000000..089327266 --- /dev/null +++ b/sum-of-two-integers/krokerdile.js @@ -0,0 +1,16 @@ +/** + * @param {number} a + * @param {number} b + * @return {number} + */ +function getSum(a, b) { + while (b !== 0) { + const sum = a ^ b; // 자리올림 없는 합 + const carry = (a & b) << 1; // 자리올림 비트 + + a = sum; + b = carry; + } + + return a; +}