-
Notifications
You must be signed in to change notification settings - Fork 126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[KwonNayeon] Week 5 #853
[KwonNayeon] Week 5 #853
Changes from all commits
091227d
6ca4a28
8154a14
d5e43c3
ab67504
22af2e7
b92c6ba
585e7fd
e8a5387
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
""" | ||
Constraints: | ||
1. 1 <= prices.length <= 10^5 | ||
2. 0 <= prices[i] <= 10^4 | ||
|
||
Time Complexity: O(n) | ||
|
||
Space Complexity: O(1) | ||
|
||
풀이 방법: | ||
- 배열을 한 번 순회하면서: | ||
1. 현재까지의 최소 가격(min_price)을 계속 갱신 | ||
2. 현재 가격에서 최소 가격을 뺀 값(현재 가능한 이익)과 기존 최대 이익을 비교하여 더 큰 값을 저장 | ||
- 이 방식으로 각 시점에서 가능한 최대 이익을 계산함 | ||
|
||
To Do: | ||
- 다른 접근 방법 찾아보기 (Two Pointers, Dynamic Programming) | ||
""" | ||
|
||
class Solution: | ||
def maxProfit(self, prices: List[int]) -> int: | ||
min_price = prices[0] | ||
max_profit = 0 | ||
|
||
for i in range(1, len(prices)): | ||
min_price = min(min_price, prices[i]) | ||
max_profit = max(max_profit, prices[i] - min_price) | ||
|
||
return max_profit | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
""" | ||
Constraints: | ||
1. 0 <= strs.length <= 200 | ||
2. 0 <= strs[i].length <= 200 | ||
3. strs[i]는 유니코드 문자들로만 구성됨 | ||
4. encode된 string은 반드시 decode 가능해야 함 | ||
|
||
Time Complexity: O(n) | ||
|
||
Space Complexity: O(n) | ||
|
||
풀이방법: | ||
- encode: 각 문자열 뒤에 '#' 추가하여 하나로 합침 | ||
- decode: '#'을 기준으로 문자열 분할 | ||
|
||
Further consideration: | ||
- 현재 방식은 입력 문자열에 '#'이 포함된 경우 문제 발생 가능 | ||
- 개선 방법: 문자열 길이 + 구분자 + 문자열 형식 사용 | ||
예: ["Hello", "World"] -> "5#Hello5#World" | ||
""" | ||
|
||
class Solution: | ||
""" | ||
@param: strs: a list of strings | ||
@return: encodes a list of strings to a single string. | ||
Examples: | ||
input: ["Hello", "World"] | ||
output: "Hello#World" | ||
""" | ||
def encode(self, strs): | ||
result = "" | ||
for s in strs: | ||
result = result + s + "#" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "#"같은 클래스의 다른 메서드에서도 사용하는 변수는 클래스 변수로 선언하고 사용하면 좋을 것 같습니다. |
||
return result[:-1] | ||
|
||
""" | ||
@param: str: A string | ||
@return: decodes a single string to a list of strings | ||
Examples: | ||
input: "Hello#World" | ||
output: ["Hello", "World"] | ||
""" | ||
def decode(self, str): | ||
return str.split("#") |
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,32 @@ | ||||||||||||
""" | ||||||||||||
Constraints: | ||||||||||||
1. 1 <= strs.length <= 10^4 | ||||||||||||
2. 0 <= strs[i].length <= 100 | ||||||||||||
3. strs[i] consists of lowercase English letters. | ||||||||||||
|
||||||||||||
Time Complexity: O(N * K * log K) | ||||||||||||
- N은 입력 문자열의 개수 (strs의 길이) | ||||||||||||
- K는 가장 긴 문자열의 길이 | ||||||||||||
- 각 문자열을 정렬하는데 K * log K가 필요하고 | ||||||||||||
- 이걸 N개의 문자열에 대해 수행 | ||||||||||||
|
||||||||||||
Space Complexity: O(N * K) | ||||||||||||
- N개의 문자열을 저장해야 함 | ||||||||||||
- 각 문자열의 길이는 최대 K | ||||||||||||
- anagram_dict에 모든 문자열을 저장하기 때문 | ||||||||||||
""" | ||||||||||||
|
||||||||||||
class Solution: | ||||||||||||
def groupAnagrams(self, strs: List[str]) -> List[List[str]]: | ||||||||||||
anagram_dict = {} | ||||||||||||
|
||||||||||||
for s in strs: | ||||||||||||
sorted_str = ''.join(sorted(s)) | ||||||||||||
|
||||||||||||
if sorted_str in anagram_dict: | ||||||||||||
anagram_dict[sorted_str].append(s) | ||||||||||||
else: | ||||||||||||
anagram_dict[sorted_str] = [s] | ||||||||||||
Comment on lines
+26
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
dict의 기본 내장 메서드를 이렇게 사용할 수도 있습니다 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 리뷰 감사합니다! @EgonD3V 님 덕분에 조건문 없이 깔끔하게 코드를 구현하는 법을 배웠어요! |
||||||||||||
|
||||||||||||
return list(anagram_dict.values()) | ||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
""" | ||
Constraints: | ||
1. 1 <= word.length, prefix.length <= 2000 | ||
2. word and prefix consist only of lowercase English letters. | ||
3. At most 3 * 10^4 calls in total will be made to insert, search, and startsWith. | ||
|
||
Time Complexity: | ||
- insert: O(m), m은 입력 단어의 길이 | ||
- search: O(m), m은 검색 단어의 길이 | ||
- startsWith: O(m), m은 접두사의 길이 | ||
|
||
Space Complexity: | ||
- O(N*M), N은 저장된 단어의 개수, M은 평균 단어 길이 | ||
|
||
이해한 내용: | ||
1. Prefix(접두사)의 의미 | ||
- 문법적 접두사(un-, pre- 등)가 아님 | ||
- 단순히 단어의 앞부분에 있는 문자열을 의미 | ||
- 예: "apple"의 접두사 -> "a", "ap", "app", "appl", "apple" | ||
|
||
2. 실행 방식 | ||
- 입력으로 주어진 명령어를 순차적으로 실행 | ||
- 예: ["Trie", "insert", "search"] 순서대로 실행 | ||
- 각 명령어에 해당하는 인자값도 순서대로 적용 | ||
|
||
3. 자료구조 선택 (Trie with Hash Table) | ||
- Trie의 각 노드에서 자식 노드를 저장할 때 해시 테이블 사용 | ||
- 키: 다음 문자, 값: 해당 문자의 TrieNode | ||
- 장점: 다음 문자 검색이 O(1)로 가능 | ||
|
||
Notes: | ||
- 혼자 구현하기 어려워서, 공부한 내용을 정리만 했습니다. | ||
""" | ||
|
||
# 트리의 각 "노드(마디)"를 표현하는 클래스 | ||
class TrieNode: | ||
def __init__(self): | ||
# children은 "다음 글자들을 저장하는 공간" | ||
# 예: 'a' 다음에 'p'가 올 수 있다면 children['p']에 저장 | ||
self.children = {} | ||
|
||
# is_end는 "여기까지가 하나의 단어가 되는지"를 표시 | ||
# 예: "app"을 저장했다면, p노드의 is_end가 True | ||
self.is_end = False | ||
Comment on lines
+37
to
+44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TreeNode가 직접 값을 들고 있지 않고 children의 key로만 들고 있으면 나중에 Trie의 다른 조건이 포함된 조회 관련 메서드를 구현할 때 불편할 것 같습니다. |
||
|
||
# 트리 전체를 관리하는 클래스 | ||
class Trie: | ||
def __init__(self): | ||
# 트리의 시작점 생성 | ||
# 실제 글자들은 root 밑에서부터 시작 | ||
self.root = TrieNode() | ||
|
||
# 새로운 단어를 트리에 추가하는 함수 | ||
def insert(self, word: str) -> None: | ||
node = self.root | ||
for char in word: | ||
if char not in node.children: | ||
node.children[char] = TrieNode() | ||
node = node.children[char] | ||
node.is_end = True | ||
|
||
# 단어가 트리에 있는지 찾는 함수 | ||
def search(self, word: str) -> bool: | ||
node = self.root | ||
for char in word: | ||
if char in node.children: | ||
node = node.children[char] | ||
else: | ||
return False | ||
return node.is_end | ||
|
||
# 해당 접두사로 시작하는 단어가 있는지 확인하는 함수 | ||
def startsWith(self, prefix: str) -> bool: | ||
node = self.root | ||
for char in prefix: | ||
if char in node.children: | ||
node = node.children[char] | ||
else: | ||
return False | ||
return True | ||
|
||
""" | ||
사용 예시: | ||
trie = Trie() | ||
trie.insert("apple") # "apple" 저장 | ||
trie.search("apple") # True 반환 (apple이 있음) | ||
trie.search("app") # False 반환 (app은 없음) | ||
trie.startsWith("app") # True 반환 (app으로 시작하는 단어가 있음) | ||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
다른 접근 방법(Two Pointers, Dynamic Programming)을 고려해 보라고 주석에 적혀 있는데, 이 코드와 비교했을 때 어떤 장단점이 있을까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lledellebell 제약조건이 추가되었을 때를 고려해볼 수 있을 것 같습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@EgonD3V 조금 늦었지만, 답변 감사합니다!