Skip to content

Commit

Permalink
Merge pull request #875 from pmjuu/main
Browse files Browse the repository at this point in the history
[Lyla] Week 05
  • Loading branch information
pmjuu authored Jan 11, 2025
2 parents 845cdbd + 6f9ddfd commit cd99cbf
Show file tree
Hide file tree
Showing 6 changed files with 201 additions and 1 deletion.
21 changes: 21 additions & 0 deletions best-time-to-buy-and-sell-stock/pmjuu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# 시간 복잡도:
# - 배열을 한 번 순회하므로 O(n) (n은 prices 배열의 길이)

# 공간 복잡도:
# - 추가 변수 2개(min_price, max_profit)를 사용하므로 O(1)

from typing import List


class Solution:
def maxProfit(self, prices: List[int]) -> int:
buy = float('inf')
profit = 0

for price in prices:
if price < buy:
buy = price
else:
profit = max(profit, price - buy)

return profit
71 changes: 71 additions & 0 deletions encode-and-decode-strings/pmjuu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# encode 메서드:
# 시간 복잡도: O(N)
# - 각 문자열을 한 번씩 순회하며 길이와 내용을 처리하므로, 모든 문자열 길이의 합에 비례.
# 공간 복잡도: O(N)
# - 인코딩된 결과 문자열을 저장하기 위해 추가 공간 사용.

# decode 메서드:
# 시간 복잡도: O(N)
# - 인코딩된 문자열을 처음부터 끝까지 한 번 순회하며 파싱하므로, 입력 문자열 길이에 비례.
# - s.find('#', i)는 인덱스 i부터 다음 #를 찾음.
# - 여러 번의 find 호출이 있더라도 각 호출마다 전체 문자열을 다시 탐색하지 않고 이전 탐색 이후의 부분만 탐색하게 되어, 모든 find 호출을 합한 전체 탐색 거리는 인코딩된 문자열의 전체 길이 n에 해당함. 전체 시간은 O(n)에 수렴.
# 공간 복잡도: O(N)
# - 디코딩된 문자열 리스트를 구성하기 위해 추가 공간 사용.


class Solution:
"""
@param strs: a list of strings
@return: encodes a list of strings to a single string.
"""
def encode(self, strs):
encoded_str = ""

for s in strs:
encoded_str += (str(len(s)) + "#" + s)

return encoded_str

"""
@param s: A string
@return: decodes a single string to a list of strings
"""
def decode(self, s):
decoded_list = []
i = 0
while i < len(s):
j = s.find("#", i)
length = int(s[i:j])
i = j + 1
decoded_list.append(s[i:i + length])
i += length

return decoded_list


def main():
sol = Solution()

# 테스트 예시 1
input_strings1 = ["lint", "code", "love", "you"]
print("===== Example 1 =====")
print("Original: ", input_strings1)
encoded_str1 = sol.encode(input_strings1)
print("Encoded: ", encoded_str1)
decoded_list1 = sol.decode(encoded_str1)
print("Decoded: ", decoded_list1)
print()

# 테스트 예시 2
input_strings2 = ["1234567890a", "we", "say", "#", "yes"]
print("===== Example 2 =====")
print("Original: ", input_strings2)
encoded_str2 = sol.encode(input_strings2)
print("Encoded: ", encoded_str2)
decoded_list2 = sol.decode(encoded_str2)
print("Decoded: ", decoded_list2)
print()


if __name__ == "__main__":
main()
22 changes: 22 additions & 0 deletions group-anagrams/pmjuu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# 시간 복잡도: O(n * m log m)
# - n: 문자열 배열의 길이, m: 각 문자열의 최대 길이
# - 각 문자열을 정렬하는 데 O(m log m) 시간이 걸리며, 모든 문자열에 대해 이를 수행
# - 문제에서 m 이 최대 100이므로, 정렬 비용은 상수에 가깝게 볼 수도 있음 (m = 100인 상황에서 100 * log(100)는 약 664 정도)

# 공간 복잡도: O(n * m)
# - 정렬된 문자열(길이 최대 m)을 키로 사용하는 딕셔너리에 최대 n개의 키가 생길 수 있음
# - 각 키에 대해 원본 문자열들을 저장하므로 O(n * m) 크기의 공간을 사용

from collections import defaultdict
from typing import List


class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
anagram_map = defaultdict(list)

for word in strs:
sorted_word = ''.join(sorted(word))
anagram_map[sorted_word].append(word)

return list(anagram_map.values())
55 changes: 55 additions & 0 deletions implement-trie-prefix-tree/pmjuu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# 시간 복잡도:
# - insert(word): O(m)
# - m은 word의 길이입니다.
# - 각 문자에 대해 트리를 탐색하거나 새 노드를 추가하므로 O(m) 시간이 걸립니다.
#
# - search(word): O(m)
# - m은 word의 길이입니다.
# - 트리의 각 문자 노드를 탐색하므로 O(m) 시간이 걸립니다.
#
# - startsWith(prefix): O(m)
# - m은 prefix의 길이입니다.
# - 트리의 각 문자 노드를 탐색하므로 O(m) 시간이 걸립니다.
#
# 공간 복잡도:
# - O(n * m)
# - n은 트리에 삽입된 단어의 개수입니다.
# - m은 각 단어의 평균 길이입니다.
# - 각 단어의 문자에 대해 새로운 노드를 생성하므로 O(n * m) 공간이 필요합니다.


class Trie:

def __init__(self):
self.children = {}
self.is_end_of_word = False

def insert(self, word: str) -> None:
current = self

for char in word:
if char not in current.children:
current.children[char] = Trie()
current = current.children[char]

current.is_end_of_word = True

def search(self, word: str) -> bool:
current = self

for char in word:
if char not in current.children:
return False
current = current.children[char]

return current.is_end_of_word

def startsWith(self, prefix: str) -> bool:
current = self

for char in prefix:
if char not in current.children:
return False
current = current.children[char]

return True
30 changes: 30 additions & 0 deletions word-break/pmjuu.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""
시간 복잡도:
- 외부 루프는 O(n), 내부 루프는 최악의 경우 각 i에 대해 O(n)만큼 실행됩니다. (n: 문자열 s의 길이)
- s[j:i]를 wordSet에서 찾는 작업은 O(1)입니다 (set 사용).
- 전체 시간 복잡도: O(n^2).
공간 복잡도:
- DP 배열은 O(n)의 공간을 차지합니다.
- wordSet은 wordDict에 있는 모든 문자의 총 길이를 기준으로 O(m)의 공간을 차지합니다. (m: wordDict의 단어 수)
- 전체 공간 복잡도: O(n + m).
"""

from typing import List


class Solution:
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
wordSet = set(wordDict)
n = len(s)

dp = [False] * (n + 1)
dp[0] = True

for i in range(1, n + 1):
for j in range(i):
if dp[j] and s[j:i] in wordSet:
dp[i] = True
break

return dp[n]
3 changes: 2 additions & 1 deletion word-search/pmjuu.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,14 @@ def search(row, col, word_idx, visited):
# => 총 공간 복잡도: O(k)


from collections import Counter

class Solution:
def exist(self, board: list[list[str]], word: str) -> bool:
n, m = len(board), len(board[0])
word_length = len(word)

# 조기 종료: board에 word를 구성할 충분한 문자가 있는지 확인
from collections import Counter
board_counter = Counter(char for row in board for char in row)
word_counter = Counter(word)
if any(word_counter[char] > board_counter[char] for char in word_counter):
Expand Down

0 comments on commit cd99cbf

Please sign in to comment.