diff --git a/best-time-to-buy-and-sell-stock/kangdaia.py b/best-time-to-buy-and-sell-stock/kangdaia.py new file mode 100644 index 0000000000..ce6352533b --- /dev/null +++ b/best-time-to-buy-and-sell-stock/kangdaia.py @@ -0,0 +1,20 @@ +class Solution: + def maxProfit(self, prices: list[int]) -> int: + """ + 주식 가격 목록에서 최대 이익을 계산하는 함수. + + 시간 복잡도: O(N) + 공간 복잡도: O(1) + + Args: + prices (list[int]): 주식 가격 목록 + + Returns: + int: 최대 이익 + """ + min_price = prices[0] + max_profit = 0 + for price in prices[1:]: + max_profit = max(max_profit, price - min_price) + min_price = min(min_price, price) + return max_profit diff --git a/encode-and-decode-strings/kangdaia.py b/encode-and-decode-strings/kangdaia.py new file mode 100644 index 0000000000..5cce3b6120 --- /dev/null +++ b/encode-and-decode-strings/kangdaia.py @@ -0,0 +1,37 @@ +class Solution: + def encode(self, strs: list[str]) -> str: + """ + 인코딩 함수 + 방식: %를 사용해 문자열의 길이 + % + 문자열로 인코딩 + + Args: + strs (list[str]): 인코딩할 문자열 목록 + + Returns: + str: 인코딩된 문자열 + """ + return "".join(f"{len(s)}%{s}" for s in strs) + + def decode(self, s: str) -> list[str]: + """ + 디코딩 함수 + 시간복잡도: O(N) + + Args: + s (str): 디코딩할 문자열 + + Returns: + list[str]: 디코딩된 문자열 목록 + """ + res = [] + i = 0 + while i < len(s): + j = i + while s[j] != "%": + j += 1 + length = int(s[i:j]) + start = j + 1 + end = start + length + res.append(s[start:end]) + i = end + return res diff --git a/group-anagrams/kangdaia.py b/group-anagrams/kangdaia.py new file mode 100644 index 0000000000..dfaf60ad5f --- /dev/null +++ b/group-anagrams/kangdaia.py @@ -0,0 +1,23 @@ +class Solution: + def groupAnagrams(self, strs: list[str]) -> list[list[str]]: + """ + 단어 목록에서 애너그램끼리 그룹화해서, 그룹화된 단어 목록을 반환하는 함수. + + N은 단어의 개수, M은 단어의 최대 길이로 가정할 때, + 시간 복잡도: O(N * M log M) + 공간 복잡도: O(N * M) + + Args: + strs (list[str]): 단어 목록 + + Returns: + list[list[str]]: 애너그램 그룹화된 단어 목록 + """ + seen = dict() + for st in strs: + st_key = "".join(sorted(st)) + if st_key in seen: + seen[st_key].append(st) + else: + seen[st_key] = [st] + return list(seen.values()) diff --git a/implement-trie-prefix-tree/kangdaia.py b/implement-trie-prefix-tree/kangdaia.py new file mode 100644 index 0000000000..6a009f8bbd --- /dev/null +++ b/implement-trie-prefix-tree/kangdaia.py @@ -0,0 +1,60 @@ +class Node: + """ + Trie 자료구조의 노드를 나타내는 클래스. + + key: 노드의 키 (문자) + data: 노드에 저장된 데이터 (단어) + children: 자식 노드들을 저장함 (키: 문자, 값: Node 객체) + """ + def __init__(self, key, data=None): + self.key = key + self.data = data + self.children = {} + + +class Trie: + """ + Trie 자료구조를 구현한 클래스. + + head: Trie의 루트 노드 + + insert(word): 단어를 Trie에 삽입하는 메서드 + search(word): Trie에서 단어가 존재하는지 확인하는 메서드 + startsWith(prefix): Trie에서 접두사가 존재하는지 확인하는 메서드 + + - 시간 복잡도: O(M) (M은 단어의 길이) + - 공간 복잡도: O(N * M) (N은 단어의 개수, M은 단어의 최대 길이) + """ + def __init__(self): + self.head = Node(None) + + def insert(self, word: str) -> None: + curr = self.head + for char in word: + if char not in curr.children: + curr.children[char] = Node(char) + curr = curr.children[char] + curr.data = word + + def search(self, word: str) -> bool: + curr = self.head + for char in word: + if char not in curr.children: + return False + curr = curr.children[char] + return True if curr.data == word else False + + def startsWith(self, prefix: str) -> bool: + curr = self.head + for char in prefix: + if char not in curr.children: + return False + curr = curr.children[char] + return True + + +# Your Trie object will be instantiated and called as such: +# obj = Trie() +# obj.insert(word) +# param_2 = obj.search(word) +# param_3 = obj.startsWith(prefix) diff --git a/word-break/kangdaia.py b/word-break/kangdaia.py new file mode 100644 index 0000000000..b063601c19 --- /dev/null +++ b/word-break/kangdaia.py @@ -0,0 +1,26 @@ +class Solution: + def wordBreak(self, s: str, wordDict: list[str]) -> bool: + """ + 주어진 문자열 s를 단어 사전 wordDict의 단어들로 분할할 수 있는지 여부를 판단하는 함수. + N은 문자열 s의 길이, M은 단어 사전의 최대 단어 길이로 가정할 때, + 시간 복잡도: O(N * M) + 공간 복잡도: O(N) + + Args: + s (str): 주어진 문자열 + wordDict (list[str]): 사용가능한 단어 사전 + + Returns: + bool: 주어진 문자열을 단어 사전의 단어들로 분할할 수 있는지 여부 + """ + word_check = [False] * (len(s) + 1) + max_len = len(max(wordDict, key=len)) + word_check[0] = True + for i in range(len(s)): + if not word_check[i]: + continue + for j in range(i + 1, min(len(s), i + max_len) + 1): + # i까지의 단어가 사전에 있고, i부터 j까지의 단어가 사전에 있으면 모든 단어가 사전에 있는 상태로 판단 + if word_check[i] and s[i:j] in wordDict: + word_check[j] = True + return word_check[-1]