diff --git a/best-time-to-buy-and-sell-stock/Blossssom.ts b/best-time-to-buy-and-sell-stock/Blossssom.ts new file mode 100644 index 0000000000..73d8d4283c --- /dev/null +++ b/best-time-to-buy-and-sell-stock/Blossssom.ts @@ -0,0 +1,16 @@ +function maxProfit(prices: number[]): number { + let min = prices[0]; + let max = 0; + + for (let i = 0; i < prices.length; i++) { + min = Math.min(min, prices[i]); + max = Math.max(max, prices[i] - min); + } + + return max; +} + +const prices = [3, 3, 5, 0, 0, 3, 1, 4]; +maxProfit(prices); + + diff --git a/encode-and-decode-strings/Blossssom.ts b/encode-and-decode-strings/Blossssom.ts new file mode 100644 index 0000000000..dde64ad335 --- /dev/null +++ b/encode-and-decode-strings/Blossssom.ts @@ -0,0 +1,47 @@ +class Solution { + private baseStr = "#"; + /* + * @param strs: a list of strings + * @return: encodes a list of strings to a single string. + */ + public encode(strs: string[]): string { + let encodedStr = ""; + for (const str of strs) { + encodedStr += `${str.length}${this.baseStr}${str}`; + } + return encodedStr; + } + + /* + * @param str: A string + * @return: decodes a single string to a list of strings + */ + public decode(str: string): string[] { + const spliter = []; + let idx = 0; + while (idx < str.length) { + let findBase = idx; + // length가 10 이상일 경우를 위해 순회하며 파싱 + while (str[findBase] !== this.baseStr) { + findBase++; + } + + const contentLength = parseInt(str.substring(idx, findBase)); + const content = str.substring(findBase + 1, findBase + contentLength + 1); + spliter.push(content); + idx = findBase + contentLength + 1; + } + return spliter; + } +} + +const input = ["lint", "code", "love", "you"]; + +const solutionInstance = new Solution(); + +const encoded = solutionInstance.encode(input); +const decoded = solutionInstance.decode(encoded); + +console.log(encoded, decoded); + + diff --git a/group-anagrams/Blossssom.ts b/group-anagrams/Blossssom.ts new file mode 100644 index 0000000000..5fd924a6e5 --- /dev/null +++ b/group-anagrams/Blossssom.ts @@ -0,0 +1,46 @@ +/** + * @param strs - 문자열 배열 + * @returns - anagram이 가능한 이중 배열 + * @description + * - 배열의 길이는 최대 10^4로 순회는 가능한 적게 + * - 문자열의 최대 길이는 100으로 널널 + * - 1. 내부 문자열 정렬 (O(N * K log K)) + * - 2. 아스키로 변환하여 1번만 순회 (O(N * K)) + * + * - 다만 문자열이 작을 경우 (현재 100 이하로 작은편) 정렬보다 배열 생성과 문자열 join이 더 무거워 질 수 있음 + * - Map을 쓰는게 조금은 더 빠를듯 + */ + +// function groupAnagrams(strs: string[]): string[][] { +// const strObj: Record = {}; +// for (let i = 0; i < strs.length; i++) { +// const sortedItem = strs[i].split("").sort().join(""); +// strObj[sortedItem] ??= []; +// strObj[sortedItem].push(strs[i]); +// } + +// return Object.values(strObj); +// } + +function groupAnagrams(strs: string[]): string[][] { + const strObj: Record = {}; + for (let i = 0; i < strs.length; i++) { + const alpha = Array.from({ length: 26 }, () => 0); + + for (const st of strs[i]) { + alpha[st.charCodeAt(0) - "a".charCodeAt(0)]++; + } + + const joinStr = alpha.join(","); + strObj[joinStr] ??= []; + strObj[joinStr].push(strs[i]); + } + + return Object.values(strObj); +} + +const strs = ["a"]; + +groupAnagrams(strs); + + diff --git a/implement-trie-prefix-tree/Blossssom.ts b/implement-trie-prefix-tree/Blossssom.ts new file mode 100644 index 0000000000..80f81eac85 --- /dev/null +++ b/implement-trie-prefix-tree/Blossssom.ts @@ -0,0 +1,99 @@ +// 단순 구현 시 효율이 낮게 나옴 +// class Trie { +// private word: Set; +// constructor() { +// this.word = new Set(); +// } + +// insert(word: string): void { +// this.word.add(word); +// } + +// search(word: string): boolean { +// return this.word.has(word); +// } + +// startsWith(prefix: string): boolean { +// for (const str of this.word) { +// if (prefix.length > str.length) { +// continue; +// } +// let check = true; +// for (let i = 0; i < prefix.length; i++) { +// if (str[i] !== prefix[i]) { +// check = false; +// break; +// } +// } +// if (check) { +// return true; +// } +// } +// return false; +// } +// } + +// 노드 구조를 개선 +class TrieNode { + children: { [key: string]: TrieNode }; + isEndOfWord: boolean; + constructor() { + this.children = {}; + this.isEndOfWord = false; + } +} + +class Trie { + private root: TrieNode; + constructor() { + this.root = new TrieNode(); + } + + insert(word: string): void { + // 글자 하나씩 TrieNode 타입으로 저장 + let currentNode = this.root; + for (const char of word) { + if (!currentNode.children[char]) { + currentNode.children[char] = new TrieNode(); + } + + currentNode = currentNode.children[char]; + } + currentNode.isEndOfWord = true; + console.log(this.root); + } + + // 각 글자를 TrieNode에서 서칭하며 판단 + search(word: string): boolean { + let currentNode = this.root; + for (const char of word) { + if (!currentNode.children[char]) { + return false; + } + currentNode = currentNode.children[char]; + } + return currentNode.isEndOfWord; + } + + // 동일 로직이지만 prefix 만큼만 존재하면 true + startsWith(prefix: string): boolean { + let currentNode = this.root; + for (const char of prefix) { + if (!currentNode.children[char]) { + return false; + } + currentNode = currentNode.children[char]; + } + return true; + } +} + +const trie = new Trie(); +trie.insert("apple"); +trie.search("apple"); // true +trie.search("app"); // false +trie.startsWith("app"); // true +trie.insert("app"); +trie.search("app"); // true + + diff --git a/word-break/Blossssom.ts b/word-break/Blossssom.ts new file mode 100644 index 0000000000..45c465bfd9 --- /dev/null +++ b/word-break/Blossssom.ts @@ -0,0 +1,35 @@ +/** + * @param s - 타겟 문자열 + * @param wordDict - 문자열 배열 + * @returns - wordDict의 요소를 조합해 타겟 문자열을 만들 수 있는지 return + * @description + * - wordDict의 요소는 중복 사용 가능 + * - dp 까진 생각했지만 세부 구현까진 힘들었음 + */ + +function wordBreak(s: string, wordDict: string[]): boolean { + // 각 요소별 남은 단어를 저장한다면? + const dictSet = new Set(wordDict); + const dp = Array.from({ length: s.length + 1 }, () => false); + + dp[0] = true; + + for (let i = 1; i <= s.length; i++) { + for (let j = 0; j < i; j++) { + if (dp[j] && dictSet.has(s.slice(j, i))) { + dp[i] = true; + break; + } + } + } + + return dp[s.length]; +} + +const s = "catsandog"; +const wordDict = ["cats", "dog", "sand", "and", "cat"]; + +const answer = wordBreak(s, wordDict); +console.log("is answer :", answer); + +