From 1dd83e61c85e3e7dd614551867a9c71334db6ac4 Mon Sep 17 00:00:00 2001 From: Hyogyeong Shin Date: Thu, 21 Aug 2025 20:39:35 +0700 Subject: [PATCH 01/12] feat: add 0221 Best Time to Buy And Sell Stock solution --- best-time-to-buy-and-sell-stock/hyogshin.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 best-time-to-buy-and-sell-stock/hyogshin.py diff --git a/best-time-to-buy-and-sell-stock/hyogshin.py b/best-time-to-buy-and-sell-stock/hyogshin.py new file mode 100644 index 000000000..50dcec57e --- /dev/null +++ b/best-time-to-buy-and-sell-stock/hyogshin.py @@ -0,0 +1,8 @@ +class Solution: + def maxProfit(self, prices: List[int]) -> int: + dp = [0] * (len(prices) + 1) + least_num = prices[0] + for i in range(len(prices)): + least_num = min(prices[i], least_num) + dp[i] = max(prices[i] - least_num, dp[i-1]) + return max(dp) From b9abf48b0976d2b74b68cd92386b547675323d53 Mon Sep 17 00:00:00 2001 From: Hyogyeong Shin Date: Thu, 21 Aug 2025 20:52:06 +0700 Subject: [PATCH 02/12] docs: add time and space complexity --- best-time-to-buy-and-sell-stock/hyogshin.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/best-time-to-buy-and-sell-stock/hyogshin.py b/best-time-to-buy-and-sell-stock/hyogshin.py index 50dcec57e..ae641ed26 100644 --- a/best-time-to-buy-and-sell-stock/hyogshin.py +++ b/best-time-to-buy-and-sell-stock/hyogshin.py @@ -1,3 +1,14 @@ +''' +문제 풀이 +- 이중 for 문으로 구현시 O(n^2) 으로 시간 초과 +- least_num에 현재 날짜 이전에 가장 싸게 살 수 있는 금액을 업데이트 +- dp로 해당 날짜까지 가장 큰 수익을 저장 +시간 복잡도: O(n) +- for 문 하나 -> O(n) +공간 복잡도: O(n) +- dp 리스트 -> O(n) +''' + class Solution: def maxProfit(self, prices: List[int]) -> int: dp = [0] * (len(prices) + 1) From 7f4ce768872159fe32e7392a8dbd5c3fcd6cadc5 Mon Sep 17 00:00:00 2001 From: Hyogyeong Shin Date: Thu, 21 Aug 2025 20:54:58 +0700 Subject: [PATCH 03/12] refactor: enhance space complexity by removing list --- best-time-to-buy-and-sell-stock/hyogshin.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/best-time-to-buy-and-sell-stock/hyogshin.py b/best-time-to-buy-and-sell-stock/hyogshin.py index ae641ed26..dc75477bf 100644 --- a/best-time-to-buy-and-sell-stock/hyogshin.py +++ b/best-time-to-buy-and-sell-stock/hyogshin.py @@ -11,9 +11,10 @@ class Solution: def maxProfit(self, prices: List[int]) -> int: - dp = [0] * (len(prices) + 1) - least_num = prices[0] + largest = 0 + least = prices[0] for i in range(len(prices)): - least_num = min(prices[i], least_num) - dp[i] = max(prices[i] - least_num, dp[i-1]) - return max(dp) + least = min(prices[i], least) + largest = max(prices[i] - least, largest) + return largest + From e6658bb94a2a720a5a05cb6aff1542c4f73fbfb9 Mon Sep 17 00:00:00 2001 From: Hyogyeong Shin Date: Thu, 21 Aug 2025 20:56:23 +0700 Subject: [PATCH 04/12] docs: update space complexity --- best-time-to-buy-and-sell-stock/hyogshin.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/best-time-to-buy-and-sell-stock/hyogshin.py b/best-time-to-buy-and-sell-stock/hyogshin.py index dc75477bf..8247d1876 100644 --- a/best-time-to-buy-and-sell-stock/hyogshin.py +++ b/best-time-to-buy-and-sell-stock/hyogshin.py @@ -5,8 +5,8 @@ - dp로 해당 날짜까지 가장 큰 수익을 저장 시간 복잡도: O(n) - for 문 하나 -> O(n) -공간 복잡도: O(n) -- dp 리스트 -> O(n) +공간 복잡도: O(1) +- 상수 변수만 사용 -> O(1) ''' class Solution: @@ -17,4 +17,5 @@ def maxProfit(self, prices: List[int]) -> int: least = min(prices[i], least) largest = max(prices[i] - least, largest) return largest - + + From 52f51714e45bce5f68203b7545c3011f14b998f3 Mon Sep 17 00:00:00 2001 From: Hyogyeong Shin Date: Sat, 23 Aug 2025 23:32:50 +0700 Subject: [PATCH 05/12] feat: add 0236 Group Anagrams solution --- group-anagrams/hyogshin.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 group-anagrams/hyogshin.py diff --git a/group-anagrams/hyogshin.py b/group-anagrams/hyogshin.py new file mode 100644 index 000000000..bb5cac956 --- /dev/null +++ b/group-anagrams/hyogshin.py @@ -0,0 +1,15 @@ +from collections import defaultdict +from typing import List +class Solution: + def groupAnagrams(self, strs: List[str]) -> List[List[str]]: + groups = defaultdict(list) + for s in strs: + cnt = [0] * 26 + for ch in s: + cnt[ord(ch) - ord('a')] += 1 + groups[tuple(cnt)].append(s) + return list(groups.values()) + +if __name__ == "__main__": + sol = Solution() + print(sol.groupAnagrams(["eat","tea","tan","ate","nat","bat"])) From 1f7de95a9dc21c7d326482d5443761eb025540fa Mon Sep 17 00:00:00 2001 From: Hyogyeong Shin Date: Sat, 23 Aug 2025 23:40:50 +0700 Subject: [PATCH 06/12] feat: add 0238 Encode and Decode Strings solution --- encode-and-decode-strings/hyogshin.py | 41 +++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 encode-and-decode-strings/hyogshin.py diff --git a/encode-and-decode-strings/hyogshin.py b/encode-and-decode-strings/hyogshin.py new file mode 100644 index 000000000..5c2dc2ce7 --- /dev/null +++ b/encode-and-decode-strings/hyogshin.py @@ -0,0 +1,41 @@ +from typing import List +class Solution: + """ + @param: strs: a list of strings + @return: encodes a list of strings to a single string. + """ + def encode(self, strs): + return ''.join(f'{len(s)}#{s}' for s in strs) + + """ + @param: str: A string + @return: decodes a single string to a list of strings + """ + def decode(self, s): + + ans = [] + i = 0 + while i < len(s): + j = i + while s[j] != '#': + j += 1 + length = int(s[i:j]) + start = j + 1 + end = start + length + ans.append(s[start:end]) + + i = end + return ans + +if __name__ == "__main__": + sol = Solution() + + cases = [ + ["abc", "a#b", "", "hello"], + ["", ""], # 빈 문자열 2개 + ["#", "##", "###"], # 해시 포함 + ] + for arr in cases: + enc = sol.encode(arr) + dec = sol.decode(enc) + print(arr == dec, arr, "->", enc[:50] + ("..." if len(enc) > 50 else "")) From fd1c08fd535f087b90a89dfea41ebd1a71000ad5 Mon Sep 17 00:00:00 2001 From: Hyogyeong Shin Date: Sat, 23 Aug 2025 23:48:43 +0700 Subject: [PATCH 07/12] feat: add 0256 Implement Trie Prefix Tree solution --- implement-trie-prefix-tree/hyogshin.py | 59 ++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 implement-trie-prefix-tree/hyogshin.py diff --git a/implement-trie-prefix-tree/hyogshin.py b/implement-trie-prefix-tree/hyogshin.py new file mode 100644 index 000000000..7b560bf23 --- /dev/null +++ b/implement-trie-prefix-tree/hyogshin.py @@ -0,0 +1,59 @@ +from typing import List + +class TrieNode: + def __init__(self): + self.children = {} + self.isEnd = False + +class Trie: + + def __init__(self): + self.root = TrieNode() + + def insert(self, word: str) -> None: + node = self.root + for ch in word: + if ch not in node.children: + node.children[ch] = TrieNode() + node = node.children[ch] + node.isEnd = True + + def search(self, word: str) -> bool: + node = self.root + for ch in word: + if ch not in node.children: + return False + node = node.children[ch] + return node.isEnd + + def startsWith(self, prefix: str) -> bool: + node = self.root + for ch in prefix: + if ch not in node.children: + return False + node = node.children[ch] + return True + +if __name__ == "__main__": + trie = Trie() + + # insert & search 테스트 + trie.insert("apple") + print(trie.search("apple")) # True + print(trie.search("app")) # False + print(trie.startsWith("app")) # True + + trie.insert("app") + print(trie.search("app")) # True + + # 추가 케이스 + trie.insert("application") + print(trie.search("application")) # True + print(trie.startsWith("appl")) # True + print(trie.search("apply")) # False + + trie.insert("bat") + trie.insert("bath") + print(trie.search("bat")) # True + print(trie.startsWith("ba")) # True + print(trie.search("bad")) # False From 3ea6a683acc9b829a69c82b953ec08734f060002 Mon Sep 17 00:00:00 2001 From: Hyogyeong Shin Date: Sat, 23 Aug 2025 23:55:10 +0700 Subject: [PATCH 08/12] feat: add 0271 Word Break solution --- word-break/hyogshin.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 word-break/hyogshin.py diff --git a/word-break/hyogshin.py b/word-break/hyogshin.py new file mode 100644 index 000000000..9d02a7cfc --- /dev/null +++ b/word-break/hyogshin.py @@ -0,0 +1,13 @@ +from typing import List + +class Solution: + def wordBreak(self, s: str, wordDict: List[str]) -> bool: + dp = [False] * (len(s) + 1) + dp[0] = True + for i in range(1, len(s) + 1): + for j in range(i): + if dp[j] and s[j:i] in wordDict: + dp[i] = True + break + return dp[len(s)] + \ No newline at end of file From 70bc66173d492ca59b8c6929cfce4084c9b07efb Mon Sep 17 00:00:00 2001 From: Hyogyeong Shin Date: Sun, 24 Aug 2025 00:00:50 +0700 Subject: [PATCH 09/12] docs: add time and space complexity --- word-break/hyogshin.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/word-break/hyogshin.py b/word-break/hyogshin.py index 9d02a7cfc..f8990767c 100644 --- a/word-break/hyogshin.py +++ b/word-break/hyogshin.py @@ -1,3 +1,18 @@ +""" +풀이 방법 +- for 루프로 주어진 문자열을 돌면서 wordDict에 있는 단어와 매칭되면 해당 인덱스 dp를 True로 변경 +- True인 dp로부터 또 다른 단어가 사전에 매칭되면 다시 dp를 True로 변경 +- 문자열 길이 인덱스의 dp[len(str)] 가 True인 경우 모든 단어가 사전에 있는 단어로 대체 가능하므로 True 반환 + +시간 복잡도: O(n^2) +- for loop * n + for loop * 최대 n -> O(n^2) +- s[j:i] 를 wordDict에서 찾는 행위 -> O(m) + +공간 복잡도: O(n) +- dp 배열 크기 -> O(n) +- wordDict 크기 -> O(m) +""" + from typing import List class Solution: @@ -10,4 +25,4 @@ def wordBreak(self, s: str, wordDict: List[str]) -> bool: dp[i] = True break return dp[len(s)] - \ No newline at end of file + From e987dba4443e31a55fbdc3cd63b6df45975fbf2d Mon Sep 17 00:00:00 2001 From: Hyogyeong Shin Date: Sun, 24 Aug 2025 00:08:03 +0700 Subject: [PATCH 10/12] docs: add time and space complexity --- implement-trie-prefix-tree/hyogshin.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/implement-trie-prefix-tree/hyogshin.py b/implement-trie-prefix-tree/hyogshin.py index 7b560bf23..e7a07cc96 100644 --- a/implement-trie-prefix-tree/hyogshin.py +++ b/implement-trie-prefix-tree/hyogshin.py @@ -1,3 +1,16 @@ +""" +풀이 방법 +- insert: 입력된 단어의 캐릭터로 for loop을 돌아 node.children에 없는 캐릭터라면 추가하고 있다면 node.isEnd = True +- search: 입력된 단어를 캐릭터 단위로 for loop을 돌고 node.children에 없다면 바로 False 반환, 만약 모든 캐릭터가 있는 경우 단어있는 확인하기 위해 isEnd 체크 +- startsWith: 입력된 prefix로 for loop을 돌아 node.children에 없다면 바로 False 반환 + +시간 복잡도: O(n) +- for loop -> O(n) + +공간 복잡도: O(n) +- Trie를 저장하는 공간 -> O(n) +""" + from typing import List class TrieNode: @@ -57,3 +70,4 @@ def startsWith(self, prefix: str) -> bool: print(trie.search("bat")) # True print(trie.startsWith("ba")) # True print(trie.search("bad")) # False + From 2e431717bf3e11342a402b3f67cda731f16c82ce Mon Sep 17 00:00:00 2001 From: Hyogyeong Shin Date: Sun, 24 Aug 2025 00:14:22 +0700 Subject: [PATCH 11/12] docs: add time and space complexity --- encode-and-decode-strings/hyogshin.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/encode-and-decode-strings/hyogshin.py b/encode-and-decode-strings/hyogshin.py index 5c2dc2ce7..2cf8ade04 100644 --- a/encode-and-decode-strings/hyogshin.py +++ b/encode-and-decode-strings/hyogshin.py @@ -1,3 +1,16 @@ +""" +풀이 방법 +- 암호화 시 (단어의 개수) + '#' + (단어) 형식 사용 + +시간 복잡도: O(n) +- encode: join 이 모든 문자열을 이어붙임 -> O(n) +- decode: while 문 -> O(n) + +공간 복잡도: O(n) +- encode: 새로운 문자열 생성 -> O(n) +- decode: ans 리스트 -> O(n) +""" + from typing import List class Solution: """ @@ -39,3 +52,5 @@ def decode(self, s): enc = sol.encode(arr) dec = sol.decode(enc) print(arr == dec, arr, "->", enc[:50] + ("..." if len(enc) > 50 else "")) + + From 2c09eef30f9060040c88e9191f2f4dc17727e12e Mon Sep 17 00:00:00 2001 From: Hyogyeong Shin Date: Sun, 24 Aug 2025 00:18:56 +0700 Subject: [PATCH 12/12] docs: add time and space complexity --- group-anagrams/hyogshin.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/group-anagrams/hyogshin.py b/group-anagrams/hyogshin.py index bb5cac956..40a6e26c5 100644 --- a/group-anagrams/hyogshin.py +++ b/group-anagrams/hyogshin.py @@ -1,3 +1,16 @@ +""" +풀이 방법 +- ord 함수를 이용해서 캐릭터 수를 기준으로 애너그램 구분 +- tuple 활용해서 키로 사용 + +시간 복잡도: O(n * k) +- 중첩 for loop: O(n * k) + +공간 복잡도: O(n) +- cnt 문자열: O(1) +- groups dict: O(n) +""" + from collections import defaultdict from typing import List class Solution: @@ -13,3 +26,4 @@ def groupAnagrams(self, strs: List[str]) -> List[List[str]]: if __name__ == "__main__": sol = Solution() print(sol.groupAnagrams(["eat","tea","tan","ate","nat","bat"])) +