diff --git a/best-time-to-buy-and-sell-stock/grapefruitgreentealoe.js b/best-time-to-buy-and-sell-stock/grapefruitgreentealoe.js new file mode 100644 index 000000000..589a2b0b9 --- /dev/null +++ b/best-time-to-buy-and-sell-stock/grapefruitgreentealoe.js @@ -0,0 +1,16 @@ +var maxProfit = function (prices) { + let minPrice = Infinity; + let maxProfit = 0; + + for (let price of prices) { + // 가장 싼 가격을 갱신 + if (price < minPrice) { + minPrice = price; + } else { + // 최대 이익을 갱신 + maxProfit = Math.max(maxProfit, price - minPrice); + } + } + + return maxProfit; +}; diff --git a/encode-and-decode-strings/grapefruitgreentealoe.js b/encode-and-decode-strings/grapefruitgreentealoe.js new file mode 100644 index 000000000..5d19b52f6 --- /dev/null +++ b/encode-and-decode-strings/grapefruitgreentealoe.js @@ -0,0 +1,46 @@ +// 네트워크 전송을 위해서 문자열 리스트를 하나의 문자열로 안전하게 합치고 +// 다시 분리하는 함수를 작성하세요. + +/** + 풀이 과정: + 구분자를 "a,b,c"와 같이 ,로 join하면, 원래 문자열에 ,가 포함될 때 깨진다. + 따라서 길이 정보를 함께 저장하거나 특수 escape 문자를 써야한다. + + + */ +/** + * Encodes a list of strings to a single string. + * @param {string[]} strs + * @return {string} + */ +function encode(strs) { + // 각 문자열 앞에 "길이#"를 붙임 + // 예: ["abc", "de"] -> "3#abc2#de" + return strs.map((s) => `${s.length}#${s}`).join(""); +} + +/** + * Decodes a single string to a list of strings. + * @param {string} s + * @return {string[]} + */ +function decode(s) { + let res = []; + let i = 0; + + while (i < s.length) { + // 1. 길이 읽기 + let j = i; + while (s[j] !== "#") j++; + let length = parseInt(s.slice(i, j), 10); + + // 2. 길이에 맞춰 문자열 추출 + let str = s.slice(j + 1, j + 1 + length); + res.push(str); + + // 3. 인덱스 이동 + i = j + 1 + length; + } + + return res; +} diff --git a/group-anagrams/grapefruitgreentealoe.js b/group-anagrams/grapefruitgreentealoe.js new file mode 100644 index 000000000..54aa3f28b --- /dev/null +++ b/group-anagrams/grapefruitgreentealoe.js @@ -0,0 +1,37 @@ +/** + * @param {string[]} strs + * @return {string[][]} + */ +var groupAnagrams = function(strs) { + const strsMap = new Map(); + for(let str of strs){ + const strArr = str.split('').sort() + const keyName = strArr.join('-') + strsMap.set(keyName,[...(strsMap.get(keyName) + ||[]),str]) + } + return Array.from(strsMap.values()) +}; + +//시간복잡도 : O(n * klogk) +// 공간복잡도 :O(n · k) + +//2.문자 빈도수 기반 키 만들기 +// 알파벳이 26뿐이므로 각 단어마다 알파벳 개수를 세서 카운트배열 만들어 이걸 키로 사용 +var groupAnagrams = function(strs) { + const map = new Map(); + + for (let str of strs) { + const count = new Array(26).fill(0); + for (let char of str) { + count[char.charCodeAt(0) - 97]++; + } + const key = count.join('#'); // 구분자 없으면 ["1","11"]과 ["11","1"] 같은 키로 오해 가능 + map.set(key, [...(map.get(key) || []), str]); + } + + return Array.from(map.values()); +}; + +//시간복잡도 : O(n * k). 정렬이 없으므로 +// 공간복잡도: O(n · k) diff --git a/implement-trie-prefix-tree/grapefruitgreentealoe.js b/implement-trie-prefix-tree/grapefruitgreentealoe.js new file mode 100644 index 000000000..4fc681e81 --- /dev/null +++ b/implement-trie-prefix-tree/grapefruitgreentealoe.js @@ -0,0 +1,37 @@ +function TrieNode() { + this.children = {}; + this.isEnd = false; +} + +function Trie() { + this.root = new TrieNode(); +} + +Trie.prototype.insert = function (word) { + let node = this.root; + for (let char of word) { + if (!node.children[char]) { + node.children[char] = new TrieNode(); + } + node = node.children[char]; + } + node.isEnd = true; +}; + +Trie.prototype.search = function (word) { + let node = this._traverse(word); + return node !== null && node.isEnd === true; +}; + +Trie.prototype.startsWith = function (prefix) { + return this._traverse(prefix) !== null; +}; + +Trie.prototype._traverse = function (str) { + let node = this.root; + for (let char of str) { + if (!node.children[char]) return null; + node = node.children[char]; + } + return node; +}; diff --git a/word-break/grapefruitgreentealoe.js b/word-break/grapefruitgreentealoe.js new file mode 100644 index 000000000..4e61414f1 --- /dev/null +++ b/word-break/grapefruitgreentealoe.js @@ -0,0 +1,109 @@ + +//1. 백트레킹 + +/** + * @param {string} s + * @param {string[]} wordDict + * @return {boolean} + */ + +function findIndexAfter(arr, startIndex, callback) { + for (let i = startIndex + 1; i < arr.length; i++) { + if (callback(arr[i], i, arr)) { + return i; + } + } + return -1; // 못 찾으면 -1 +} + +var wordBreak = function(s, wordDict) { + let current = ''; + const dp = new Array(s.length).fill(''); + for(let i=0;i e == current+s[i] ) + if(isSegment) { + dp[i] = current + s[i] + current = '' + }else{ + current += s[i] + } + + if(current.length == s.length && i == s.length-1){ + return dp[i] ? true:false + } + + // 문자열이 저장이 되어있는 위치에 다시 돌아간다. + // 그 위치에 빈 문자열을 넣어준 후 다음 index로 돌아가게끔 한다. + if(i == s.length-1 && dp[s.length-1] == ''){ + i = dp.findLastIndex(e => e!=='') + current = dp[i] + dp[i] = ''; + } + } + return dp[s.length-1] ? true:false + +}; + + +// 가장 초기값으로 들어가게 되면, 또 같은일을 여러번 반복하게 되므로, 가장 큰 값으로 돌아가야하는게 맞다. +// 그런데 그만큼, 더 오래걸리는 경우가 발생한다. + +/*시간복잡도: O(n² * m) (n: 문자열 길이, m: wordDict 길이) +공간복잡도: O(n) +*/ + +//2. 실패난 지점을 메모이제이션 하기 : 시간리밋이 난 이유는, 이전에 실패난 지점에 대해서 다시 돌아간다는 문제가 있었기 때문에, word의 시작기점으로 잡으면 무조건 실패가 나는 index를 메모이제이션 한다. + +/** + * @param {string} s + * @param {string[]} wordDict + * @return {boolean} + */ +var wordBreak = function(s, wordDict) { + const wordSet = new Set(wordDict); //중복이 되지 않게 만든다. + const failed = new Set(); //실패한 인덱스를 기록한다. + + function dfs(start){ + if(start === s.length) return true; // 성공 + if(failed.has(start)) return false; //여길 기점으로 하면 실패한다는 것을 기록. + + for(let end = start+1; end<=s.length; end++){ + const word = s.slice(start,end); + if(wordSet.has(word) && dfs(end)){ // 여기서 잘랐을 때 가능한지. + return true; + } + } + failed.add(start); + return false; + } + return dfs(0); +}; + +/* +시간복잡도: O(n^2) + 메모이제이션으로 최적화 +공간복잡도 : O(n) : 재귀스택, failed set +*/ + +//3. dp를 활용하여, 이중 포문으로 j,i 사이에 가능한 부분이 있는지 확인한다. + +var wordBreak = function(s, wordDict) { + const wordSet = new Set(wordDict); + const dp = new Array(s.length + 1).fill(false); + dp[0] = true; // 빈 문자열은 항상 가능 + + for (let i = 1; i <= s.length; i++) { + for (let j = 0; j < i; j++) { + if (dp[j] && wordSet.has(s.slice(j, i))) { + dp[i] = true; + break; // 더 이상 검사 안 해도 됨 + } + } + } + + return dp[s.length]; +}; + +/* +시간복잡도: O(n^2) +공간복잡도 : O(n) +*/