Skip to content
Merged
21 changes: 21 additions & 0 deletions best-time-to-buy-and-sell-stock/hyogshin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'''
문제 풀이
- 이중 for 문으로 구현시 O(n^2) 으로 시간 초과
- least_num에 현재 날짜 이전에 가장 싸게 살 수 있는 금액을 업데이트
- dp로 해당 날짜까지 가장 큰 수익을 저장
시간 복잡도: O(n)
- for 문 하나 -> O(n)
공간 복잡도: O(1)
- 상수 변수만 사용 -> O(1)
'''

class Solution:
def maxProfit(self, prices: List[int]) -> int:
largest = 0
least = prices[0]
for i in range(len(prices)):
least = min(prices[i], least)
largest = max(prices[i] - least, largest)
return largest


56 changes: 56 additions & 0 deletions encode-and-decode-strings/hyogshin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""
풀이 방법
- 암호화 시 (단어의 개수) + '#' + (단어) 형식 사용

시간 복잡도: 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:
"""
@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):
Comment on lines +23 to +27
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

주석까지 보기 좋습니다!


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 ""))


29 changes: 29 additions & 0 deletions group-anagrams/hyogshin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""
풀이 방법
- 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:
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"]))

73 changes: 73 additions & 0 deletions implement-trie-prefix-tree/hyogshin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""
풀이 방법
- 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:
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

28 changes: 28 additions & 0 deletions word-break/hyogshin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""
풀이 방법
- 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:
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)]