diff --git a/clone-graph/jdy8739.js b/clone-graph/jdy8739.js new file mode 100644 index 000000000..1754bdb27 --- /dev/null +++ b/clone-graph/jdy8739.js @@ -0,0 +1,82 @@ +/** + * // Definition for a _Node. + * function _Node(val, neighbors) { + * this.val = val === undefined ? 0 : val; + * this.neighbors = neighbors === undefined ? [] : neighbors; + * }; + */ + +/** + * @param {_Node} node + * @return {_Node} + */ +var cloneGraph = function (node) { + const nodeMap = new Map(); + + const dfs = (nodeParam) => { + if (!nodeParam) { + return null; + } + + if (nodeMap.has(nodeParam.val)) { + return nodeMap.get(nodeParam.val); + } + + const clone = new Node(nodeParam.val); + + nodeMap.set(clone.val, clone); + + for (const nei of nodeParam.neighbors) { + clone.neighbors = [...clone.neighbors, dfs(nei)]; + } + + return clone; + } + + return dfs(node); +}; + +// 재귀를 활용한 dfs를 사용한 풀이 +// 시간복잡도 O(n + e) -> n(노드의 수) + e(간선의 수) 만큼 탐색을 수행 +// 공간복잡도 O(n) -> map이 총 노드의 수 만큼 크기를 가짐 + +// ------------------------------------ + +/** + * @param {_Node} node + * @return {_Node} + */ +var cloneGraph = function(node) { + if (!node) { + return null; + } + + const clone = new Node(node.val); + + const clonedNodeMap = new Map().set(clone.val, clone); + + // 이 queue에는 클론이 아니라 원본 노드가 들어가야함(neighbors에 대한 참조 때문) + const queue = [node]; + + while (queue.length > 0) { + const currentNode = queue.pop(); + + const currentNodeClone = clonedNodeMap.get(currentNode.val); + + for (const nei of currentNode.neighbors) { + if (!clonedNodeMap.has(nei.val)) { + clonedNodeMap.set(nei.val, new Node(nei.val)); + queue.push(nei); + } + + currentNodeClone.neighbors = [...currentNodeClone.neighbors, clonedNodeMap.get(nei.val)]; + } + } + + return clone; +}; + +// 큐를 활용한 bfs를 사용한 풀이 +// 시간복잡도 O(n + e) -> n(노드의 수) + e(간선의 수) 만큼 탐색을 수행 +// 공간복잡도 O(n) -> map이 총 노드의 수 만큼 크기를 가짐 + diff --git a/longest-common-subsequence/jdy8739.js b/longest-common-subsequence/jdy8739.js new file mode 100644 index 000000000..ca2409e10 --- /dev/null +++ b/longest-common-subsequence/jdy8739.js @@ -0,0 +1,35 @@ +/** + * @param {string} text1 + * @param {string} text2 + * @return {number} + */ +var longestCommonSubsequence = function(text1, text2) { + const resultMap = new Map(); + + const dfs = (i, j) => { + const mapKey = `${i}-${j}`; + + if (resultMap.has(mapKey)) { + return resultMap.get(mapKey); + } + + if (i === text1.length || j === text2.length) { + return 0; + } + + if (text1[i] === text2[j]) { + const resultHit = 1 + dfs(i + 1, j + 1); + resultMap.set(mapKey, resultHit); + return resultHit; + } + + const resultMiss = Math.max(dfs(i + 1, j), dfs(i, j + 1)); + resultMap.set(mapKey, resultMiss); + return resultMiss; + } + + return dfs(0, 0); +}; + +// 시간복잡도 O(m * n) -> 재귀를 통해 m과 n이 1씩 증가하면서 상대편의 m or n 번 째 인덱스 문자열을 비교하므로??? (잘 모르겠습니다. 리뷰어분이 여유되시면 설명부탁드립니다 ㅜㅜ) +// 공간복잡도 O(m * n) -> 맵에 키가 m * n개로 최대로 요소가 들어옴 diff --git a/longest-repeating-character-replacement/jdy8739.js b/longest-repeating-character-replacement/jdy8739.js new file mode 100644 index 000000000..73fc8b299 --- /dev/null +++ b/longest-repeating-character-replacement/jdy8739.js @@ -0,0 +1,51 @@ +/** + * @param {string} s + * @param {number} k + * @return {number} + */ +var characterReplacement = function(s, k) { + let start = 0; + let end = 0; + let maxLength = 0; + let maxCountOfChar = 0; + + const charMap = new Map(); + charMap.set(s[end], 1); + + while (end < s.length) { + maxCountOfChar = Math.max(maxCountOfChar, charMap.get(s[end])); + + const currLength = end - start + 1; + + const countOfOthers = currLength - maxCountOfChar; + + // 현재 문자열의 길이에서 가장 많이 나오는 문자열의 수를 뺸 값인 countOfOthers가 + // k보다 작으면 현재 문자열에서 start번 째 문자의 수를 map에서 감소시키고 star의 값을 증가시킨다. + if (countOfOthers > k) { + const startCharCount = charMap.get(s[start]); + charMap.set(s[start], startCharCount - 1); + + start++; + } else { + // countOfOthers가 k보다 같거나 작을 경우 k번 문자를 바꾸는 것으로 현재 문자열을 모두 하나의 문자로 통일시킬 수 있다는 것으로 + // 현재 문자열에서 end번 째 문자의 수를 map에서 증가시킨다. + // 이후 end의 값을 증가시킨다. + end++; + + const endCharCount = charMap.get(s[end]); + + if (endCharCount) { + charMap.set(s[end], endCharCount + 1); + } else { + charMap.set(s[end], 1); + } + } + + maxLength = Math.max(maxLength, Math.min(maxCountOfChar + k, currLength)); + } + + return maxLength; +}; + +// 시간복잡도 O(n) -> 슬라이딩 윈도우기법으로 최대 1번 순회한다. +// 공간복잡도 O(1) -> map의 크기는 알파벳의 갯수인 최대 26개이다. diff --git a/number-of-1-bits/jdy8739.js b/number-of-1-bits/jdy8739.js new file mode 100644 index 000000000..ea67d4408 --- /dev/null +++ b/number-of-1-bits/jdy8739.js @@ -0,0 +1,34 @@ +/** + * @param {number} n + * @return {number} + */ +var hammingWeight = function (n) { + const binary = [1]; + + while (binary[0] < n) { + const latest = binary[0] * 2; + + binary.unshift(latest); + } + + let count = 0; + + for (let i = 0; i < binary.length; i++) { + if (binary[i] <= n) { + count++; + n = n - binary[i]; + } + + if (n === 0) { + break; + } + } + + return count; +}; + +// 시간복잡도 O(logn) -> 이진탐색처럼 2씩 곱해가며 n을 넘어가는 가장 큰 수를 찾으므로 + +// 수정된 시간복잡도 -> 위의 while 문에서 O(logn)의 시간복잡도를 수행하면서 O(n)의 시간복잡도를 갖는 unshift 메소드를 사용하며 +// for문에서 다시 O(logn)의 시간복잡도의 루프를 돌기 때문에 +// 총 복잡도는 O(logn) * binary 배열의 길이 + O(logn)