diff --git a/best-time-to-buy-and-sell-stock/YeomChaeeun.ts b/best-time-to-buy-and-sell-stock/YeomChaeeun.ts new file mode 100644 index 000000000..9c5bf897f --- /dev/null +++ b/best-time-to-buy-and-sell-stock/YeomChaeeun.ts @@ -0,0 +1,19 @@ +/** + * 최대 수익을 구하는 알고리즘 + * 알고리즘 복잡도 + * - 시간 복잡도: O(n) + * - 공간 복잡도: O(1) + * @param prices + */ +function maxProfit(prices: number[]): number { + let min = prices[0] + let total = 0 + + for(let i = 1 ; i < prices.length ; i++) { + min = Math.min(min, prices[i]) + // console.log(dp[i],'===', dp[i-1], '===', prices[i]) + total = Math.max(total, prices[i] - min) + } + + return total +} diff --git a/group-anagrams/YeomChaeeun.ts b/group-anagrams/YeomChaeeun.ts new file mode 100644 index 000000000..d7f01940d --- /dev/null +++ b/group-anagrams/YeomChaeeun.ts @@ -0,0 +1,24 @@ +/** + * 애너그램 그룹화하기 + * n - 입력 문자열 배열의 길이 + * k - 가장 긴 문자열의 길이 + * + * 알고리즘 복잡도 + * - 시간 복잡도: n * k * logk (sort가 klogk 시간 소요) + * - 공간 복잡도: n * k + * @param strs + */ +function groupAnagrams(strs: string[]): string[][] { + let group = {} + + for(const s of strs) { + let key = s.split('').sort().join(''); + if(!group[key]) { + group[key] = [] + } + group[key].push(s) + } + // console.log(group) + + return Object.values(group) +} diff --git a/implement-trie-prefix-tree/YeomChaeeun.ts b/implement-trie-prefix-tree/YeomChaeeun.ts new file mode 100644 index 000000000..c0ecb44d8 --- /dev/null +++ b/implement-trie-prefix-tree/YeomChaeeun.ts @@ -0,0 +1,54 @@ +/** + * 트라이 알고리즘 + * 달레 해설을 보고 참고하여 TypeScript로 작성 + */ +class Node { + children: { [key: string]: Node }; + ending: boolean; + + constructor(ending: boolean = false) { + this.children = {}; + this.ending = ending; + } +} + +class Trie { + private root: Node; + + constructor() { + this.root = new Node(true); + } + + insert(word: string): void { + let node = this.root; + for (const ch of word) { + if (!(ch in node.children)) { + node.children[ch] = new Node(); + } + node = node.children[ch]; + } + node.ending = true; + } + + search(word: string): boolean { + let node = this.root; + for (const ch of word) { + if (!(ch in node.children)) { + return false; + } + node = node.children[ch]; + } + return node.ending; + } + + startsWith(prefix: string): boolean { + let node = this.root; + for (const ch of prefix) { + if (!(ch in node.children)) { + return false; + } + node = node.children[ch]; + } + return true; + } +} diff --git a/word-break/YeomChaeeun.ts b/word-break/YeomChaeeun.ts new file mode 100644 index 000000000..34f35a0c0 --- /dev/null +++ b/word-break/YeomChaeeun.ts @@ -0,0 +1,46 @@ +/** + * 주어진 단어가 wordDict에 있는 단어들로 분할 가능한지 확인하기 + * 알고리즘 복잡도 + * - 시간 복잡도: O(nmk) => 문자열 s의 길이 * wordDict 단어 개수 * wordDict 내 가장 긴 단어의 길이 + * - 공간 복잡도: O(n) + * @param s + * @param wordDict + */ +function wordBreak(s: string, wordDict: string[]): boolean { + // 접근 1 - 단어 포함 여부만 고려하고 여러번 사용될 있고 연속성 검사를 하지 않았음 + // let len = 0; + // for(const word of wordDict) { + // len += word.length + // if(!s.includes(word)) return false + // } + // if(s.length < len) return false + // return true + + /* 해당 케이스에서 에러 발생함 + * - 단어가 여러번 사용될 수 있기 때문 + * s="bb" + * wordDict = ["a","b","bbb","bbbb"] + */ + + // 접근 2- dp 알고리즘 적용 + // 각 위치까지의 문자열이 분할 가능한지 저장함 + let dp: boolean[] = new Array(s.length).fill(false) + + for (let i = 0; i < s.length; i++) { + for (let word of wordDict) { + // 조건 처리 - 현재 위치가 단어 길이보다 작으면 스킵함 + if (i < word.length - 1) { + continue + } + // 현재 위치의 유효성 체크 - 첫번째 단어이거나 이전 위치까지 분할 가능한지 + if (i == word.length - 1 || dp[i - word.length]) { + // 현재 위치의 단어 매칭 체크 + if (s.substring(i - word.length + 1, i + 1) == word) { + dp[i] = true + break + } + } + } + } + return dp[s.length - 1] +}