Skip to content

Commit f1f3e4e

Browse files
authored
Merge pull request #866 from sungjinwi/main
[suwi] Week 05
2 parents 2929b35 + b74d250 commit f1f3e4e

File tree

4 files changed

+157
-0
lines changed

4 files changed

+157
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""
2+
TC : O(N)
3+
for문 한 번 => O(N)
4+
5+
SC : O(1)
6+
변수 3개 선언 이외에 추가적으로 사용하는 메모리 없으므로
7+
"""
8+
9+
class Solution:
10+
def maxProfit(self, prices: List[int]) -> int:
11+
max_profit = 0
12+
buy = prices[0]
13+
sell = prices[0]
14+
for price in prices:
15+
if price < buy:
16+
buy = price
17+
sell = price
18+
if price > sell:
19+
sell = price
20+
max_profit = max(max_profit, sell - buy)
21+
return max_profit

group-anagrams/sungjinwi.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""
2+
anagram은 sort하면 동일하다는 성질을 이용해서
3+
sorted str을 key로 문자열 str배열을 value로 가지는 딕셔너리를 만든다
4+
ans은 컴프리헨션을 이용해 딕셔너리의 value를 배열에 넣어 만든다
5+
6+
TC : O(WlogW * N)
7+
strs의 평균문자열길이 W, strs의 개수를 N이라고 할 떄
8+
sort의 시간복잡도 => WlogW
9+
for문 => N
10+
11+
SC : O(W * N)
12+
anagrams가 차지하는 공간은 문자열의 길이와 개수에 비례한다
13+
14+
15+
- defaultdict 만들 때 인자로 빈배열([])이 아닌 타입(list)을 넣어줘야한다
16+
17+
- 알고달레의 다른풀이로 문자열에 나오는 알파벳 빈도 수(count = [0] * 26)로 anagram을 판별하는 법도 있다
18+
딕셔너리의 key는 불변해야 하기 때문에 count를 튜플로 바꾸는 것 주의
19+
20+
"""
21+
22+
from collections import defaultdict
23+
24+
class Solution:
25+
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
26+
anagrams = defaultdict(list)
27+
for s in strs:
28+
sorted_s = "".join(sorted(s))
29+
if sorted_s in anagrams:
30+
anagrams[sorted_s].append(s)
31+
else:
32+
anagrams[sorted_s] = [s]
33+
ans = [value for value in anagrams.values()]
34+
return ans
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
"""
2+
풀이 : 딕셔너리를 통해 트리구현
3+
- 생성자 함수는 맨 처음 노드를 만드는 역할, search("")를 위해 "ending":True로 초기화
4+
- insert함수를 수행하면 노드는 다음 문자에 대해서도 각각 노드를 가지고 있음
5+
ex) insert("a"); insert("b")
6+
{
7+
"ending":True,
8+
"a" :{"ending":True},
9+
"b" :{"ending":True}
10+
}
11+
- insert(): word의 순서대로 다음 문자의 노드(존재하지 않으면 {"ending":False}로 초기화)로 이동함
12+
for문 끝난 후 마지막 문자에서는 해당 노드로 끝나는 단어가 있다는 의미로 "ending":True로 수정
13+
14+
- search(): word 다음 문자의 노드로 이동하면서 존재하지 않으면 return False
15+
문자의 끝에 도달하면 끝나는 단어가 있는지 node["ending"] return
16+
17+
- startsWith(): prefix 다음 문자의 노드로 이동하면서 존재하지 않으면 return False
18+
문자의 끝에 도달하면 return True
19+
20+
TC : O(N)
21+
단어의 길이(N)에 비례한다
22+
SC : O(N)
23+
insert할 단어의 길이(N)에 비례해서 노드가 생성된다
24+
25+
- 딕셔너리가 아닌 class로 풀이할 수도 있다
26+
"""
27+
28+
class Trie:
29+
30+
def __init__(self):
31+
self.root = {"ending":True}
32+
33+
def insert(self, word: str) -> None:
34+
node = self.root
35+
for char in word:
36+
if char not in node:
37+
node[char] = {"ending": False}
38+
node = node[char]
39+
node["ending"] = True
40+
41+
def search(self, word: str) -> bool:
42+
node = self.root
43+
for char in word:
44+
if char in node:
45+
node = node[char]
46+
else:
47+
return False
48+
return node["ending"]
49+
50+
51+
def startsWith(self, prefix: str) -> bool:
52+
node = self.root
53+
for char in prefix:
54+
if char in node:
55+
node = node[char]
56+
else:
57+
return False
58+
return True
59+
60+
61+
# Your Trie object will be instantiated and called as such:
62+
# obj = Trie()
63+
# obj.insert(word)
64+
# param_2 = obj.search(word)
65+
# param_3 = obj.startsWith(prefix)

word-break/sungjinwi.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"""
2+
풀이 :
3+
dp 배열은 s에서 길이n까지의 문자열이 word를 통해 만들어질 수 있는지 여부를 저장
4+
dp[0]은 빈 문자열이므로 True 나머지는 False로 초기화 (총 길이가 len(s) + 1)
5+
wordDict를 순회하면서
6+
길이 n까지의 문자열이 word로 끝나는지
7+
n - len(word) 길이가 word로 만들어질 수 있는지 (dp[n - len(word)])
8+
9+
두 조건 만족하면 dp[n]=True
10+
dp의 마지막 성분을 return
11+
12+
13+
word의 갯수 W, 문자열 s의 길이 S
14+
15+
TC : O(S^2 * W)
16+
각각에 대해 for문 -> S * W
17+
s에서 word와 비교할 부분문자열 만들 때 -> S
18+
19+
SC : O(S)
20+
len(s)만큼 배열 dp를 할당
21+
22+
유의사항
23+
- dp의 첫번째 요소
24+
- if dp[n]일 때 break를 통해 최적화할 것
25+
- TC구할 때 부분문자열 구하는 복잡도 고려
26+
"""
27+
28+
class Solution:
29+
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
30+
dp = [True] + [False] * len(s)
31+
for n in range(1, len(s) + 1):
32+
for word in wordDict:
33+
if s[n - len(word):n] == word and dp[n - len(word)]:
34+
dp[n] = True
35+
if dp[n]:
36+
break
37+
return dp[-1]

0 commit comments

Comments
 (0)