diff --git a/clone-graph/uraflower.js b/clone-graph/uraflower.js new file mode 100644 index 000000000..d9a6a007e --- /dev/null +++ b/clone-graph/uraflower.js @@ -0,0 +1,31 @@ +// Definition for a _Node. +function _Node(val, neighbors) { + this.val = val === undefined ? 0 : val; + this.neighbors = neighbors === undefined ? [] : neighbors; +}; + +/** + * 그래프를 깊은 복사하여 반환하는 함수 + * @param {_Node} node + * @return {_Node} + */ +const cloneGraph = function (node) { + if (!node) return null; + + function dfs(node, visited) { + const current = new _Node(node.val); + visited.set(node, current); + + node.neighbors.forEach((neighbor) => { + const clonedNeighbor = visited.has(neighbor) ? visited.get(neighbor) : dfs(neighbor, visited); + current.neighbors.push(clonedNeighbor); + }); + + return current; + } + + return dfs(node, new Map()); // visited: 원본 노드를 key, 클론한 노드를 value로 하는 맵 +}; + +// 시간복잡도: O(V + E) (모든 노드와 간선을 한 번씩 순회) +// 공간복잡도: O(V) (visited 맵 + 재귀 호출 스택) diff --git a/longest-common-subsequence/uraflower.js b/longest-common-subsequence/uraflower.js new file mode 100644 index 000000000..b0e5aa347 --- /dev/null +++ b/longest-common-subsequence/uraflower.js @@ -0,0 +1,36 @@ +/** + * 가장 긴 공통 부분 수열의 길이를 반환하는 함수 + * @param {string} text1 + * @param {string} text2 + * @return {number} + */ +const longestCommonSubsequence = function (text1, text2) { + const dp = Array.from({ length: text1.length }, () => Array.from({ length: text2.length }, () => -1)); + + // text1, 2를 순회하는 포인터 i, j를 두고, 두 문자끼리 비교하는 함수 + function dfs(i, j) { + // 포인터가 범위를 넘어가면 백트래킹 + if (i === text1.length || j === text2.length) { + return 0; + } + + // 두 문자를 이미 비교한 적 있는 경우 해당 결과 반환 + if (dp[i][j] !== -1) { + return dp[i][j]; + } + + // 두 문자를 비교 + if (text1[i] === text2[j]) { + dp[i][j] = 1 + dfs(i + 1, j + 1); + } else { + dp[i][j] = Math.max(dfs(i + 1, j), dfs(i, j + 1)); + } + + return dp[i][j]; + } + + return dfs(0, 0); +}; + +// 시간복잡도: O(m * n) (m: text1.length, n: text2.length) +// 공간복잡도: O(m * n) (재귀 호출 깊이: m + n, dp 배열 크기: m * n) diff --git a/longest-repeating-character-replacement/uraflower.js b/longest-repeating-character-replacement/uraflower.js new file mode 100644 index 000000000..1f094c243 --- /dev/null +++ b/longest-repeating-character-replacement/uraflower.js @@ -0,0 +1,32 @@ +/** + * 주어진 문자열에서 최대 k개를 대체해 가장 긴 동일 문자 반복 부분 문자열을 만들 수 있을 때, + * 이 문자열의 길이를 반환하는 함수 + * @param {string} s + * @param {number} k + * @return {number} + */ + const characterReplacement = function(s, k) { + let start = 0; + let end = 0; + let counter = {}; + let maxFrequent = 0; // 현재 구간에 가장 많이 포함되어 있는 알파벳의 총 개수 + let maxLength = 0; + + while (start <= end && end < s.length) { + counter[s[end]] = (counter[s[end]] || 0) + 1; + maxFrequent = Math.max(maxFrequent, counter[s[end]]); + + while (end - start + 1 - maxFrequent > k) { + counter[s[start]]--; + start++; + } + + maxLength = Math.max(end - start + 1, maxLength); + end++; + } + + return maxLength; +}; + +// 시간복잡도: O(n) +// 공간복잡도: O(1) diff --git a/palindromic-substrings/uraflower.js b/palindromic-substrings/uraflower.js new file mode 100644 index 000000000..330cc13ec --- /dev/null +++ b/palindromic-substrings/uraflower.js @@ -0,0 +1,26 @@ +/** + * 회문인 부분 문자열의 개수를 반환하는 함수 + * @param {string} s + * @return {number} + */ +const countSubstrings = function(s) { + let count = 0; + + for (let i = 0; i