Skip to content

Commit 7ccab91

Browse files
authored
Merge pull request #1974 from unpo88/main
[unpo88] WEEK 01 solutions
2 parents 3fb558a + 288366e commit 7ccab91

File tree

5 files changed

+331
-0
lines changed

5 files changed

+331
-0
lines changed

β€Žcontains-duplicate/unpo88.pyβ€Ž

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
class Solution:
2+
def containsDuplicate(self, nums: list[int]) -> bool:
3+
return len(set(nums)) != len(nums)
4+
5+
"""
6+
================================================================================
7+
풀이 κ³Όμ •
8+
================================================================================
9+
10+
[1μ°¨ μ‹œλ„] Counterλ₯Ό μ΄μš©ν•œ Hash Table
11+
────────────────────────────────────────────────────────────────────────────────
12+
1. Hashing을 μ΄μš©ν•΄μ„œ 숫자 Countλ₯Ό ν•œ κ²ƒμ—μ„œ κ°œμˆ˜κ°€ 2이상인 것을 λ½‘μœΌλ©΄ λ˜κ² λŠ”λ°?
13+
14+
nums_count = Counter(nums)
15+
for count in nums_count.values():
16+
if count >= 2:
17+
return True
18+
return False
19+
20+
2. 속도가 많이 λŠλ¦¬λ„€ 더 쒋은 방법은 μ—†μ„κΉŒ?
21+
22+
23+
[2μ°¨ μ‹œλ„] Early Return with Hash Table
24+
────────────────────────────────────────────────────────────────────────────────
25+
3. 해싱을 λ§Œλ“€λ©΄μ„œ 2개 이상이면 즉각 return ν•˜λ„λ‘ κ΅¬ν˜„ν•΄λ³ΌκΉŒ?
26+
27+
nums_count = defaultdict(int)
28+
for num in nums:
29+
nums_count[num] += 1
30+
31+
if nums_count[num] == 2:
32+
return True
33+
return False
34+
35+
4. κ·Έλž˜λ„ 속도가 많이 κ°œμ„ λ˜μ§€λŠ” μ•Šμ•˜λ„€?
36+
37+
38+
[μ΅œμ’… κ°œμ„ ] Set을 μ΄μš©ν•œ 비ꡐ
39+
────────────────────────────────────────────────────────────────────────────────
40+
5. 속도λ₯Ό 획기적으둜 κ°œμ„ ν•˜λ €λ©΄ μ–΄λ–»κ²Œ μ ‘κ·Όν•΄λ³Ό 수 μžˆμ„κΉŒ?
41+
6. set으둜 쀑볡을 μ œκ±°ν•œλ‹€μŒμ— 개수λ₯Ό 비ꡐ해볼 수 μžˆμ§€ μ•ŠμœΌλ €λ‚˜?
42+
43+
return len(set(nums)) != len(nums)
44+
45+
7. 쑰금 더 속도가 λΉ¨λΌμ‘Œλ‹€.
46+
47+
48+
[μ„±λŠ₯ 뢄석]
49+
────────────────────────────────────────────────────────────────────────────────
50+
8. 근데 잘 생각해보면 Big-O μ‹œκ°„ λ³΅μž‘λ„λŠ” O(n) 일 것 같은데
51+
9. 그러면 Early Return을 ν•΄μ£ΌλŠ” 방법 2κ°€ 더 λΉ λ₯΄λ‹€κ³  μƒκ°ν–ˆλŠ”λ° μ™œ 3번 방식이 더 λΉ λ₯ΌκΉŒ?
52+
10. set이 CPython λ‚΄λΆ€μ—μ„œ C μ½”λ“œλ‘œ μ‹€ν–‰λ˜λŠ”κ΅¬λ‚˜ OK
53+
"""

β€Žhouse-robber/unpo88.pyβ€Ž

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
class Solution:
2+
def rob(self, nums: list[int]) -> int:
3+
hash_value = {}
4+
5+
def dfs(start):
6+
if start in hash_value:
7+
return hash_value[start]
8+
9+
if not start < len(nums):
10+
hash_value[start] = 0
11+
else:
12+
hash_value[start] = max(nums[start] + dfs(start+2), dfs(start+1))
13+
return hash_value[start]
14+
15+
return dfs(0)
16+
17+
"""
18+
================================================================================
19+
풀이 κ³Όμ •
20+
================================================================================
21+
22+
1. μ–‘ μ˜†μ„ μ œμ™Έν•œ μˆ«μžλ“€μ˜ 합을 κ΅¬ν•΄μ•Όν•˜λ„€?
23+
2. 첫 번째λ₯Ό μ„ νƒν•˜λ©΄ β†’ μ„Έ 번째 ~ N번째 λ“€μ˜ 뢀뢄합을 κ΅¬ν•˜λŠ” 것
24+
3. 두 번째λ₯Ό μ„ νƒν•˜λ©΄ β†’ λ„€ 번째 ~ N번째 λ“€μ˜ 뢀뢄합을 κ΅¬ν•˜λŠ” 것
25+
4. λ­”κ°€ μž¬κ·€μ μœΌλ‘œ ꡬ할 수 μžˆμ„ 것 같은데..?
26+
5. 첫 번째 μ„ νƒν•œ 것과 두 번째 μ„ νƒν•œ 것 쀑 μ–΄λŠκ²ƒμ΄ 더 큰지 비ꡐ해보면 될 것 같은데?
27+
6. 첫 번째λ₯Ό μ„ νƒν•œ 것은 β†’ nums[0] + μž¬κ·€(nums[2:])
28+
7. 두 번째λ₯Ό μ„ νƒν•œ 것은 β†’ μž¬κ·€(nums[1:])
29+
8. 그럼 μž¬κ·€ν•¨μˆ˜μ˜ λ‘œμ§μ€ μ–΄λ–»κ²Œ λ˜μ–΄μ•Όν•˜μ§€?
30+
31+
32+
[1μ°¨ μ‹œλ„] 순수 μž¬κ·€ - μ‹œκ°„ 초과
33+
────────────────────────────────────────────────────────────────────────────────
34+
9. 기본적인 μž¬κ·€ ꡬ쑰 κ΅¬ν˜„
35+
36+
def dfs(start):
37+
if start >= len(nums):
38+
return 0
39+
return max(nums[start] + dfs(start + 2), dfs(start + 1))
40+
41+
return dfs(0)
42+
43+
10. μ‹œκ°„ μ΄ˆκ³Όκ°€ λ°œμƒν–ˆλ„€?
44+
45+
46+
11. 쀑간 결과값듀을 μ €μž₯ν•˜κ³  μžˆμ–΄μ•Όν•  것 같은데
47+
12. ν•΄μ‹±μœΌλ‘œ μ €μž₯해놓고 μžˆμ–΄λ³΄μž
48+
49+
hash_value = {}
50+
51+
def dfs(start):
52+
if start in hash_value:
53+
return hash_value[start]
54+
55+
if not start < len(nums):
56+
hash_value[start] = 0
57+
else:
58+
hash_value[start] = max(nums[start] + dfs(start+2), dfs(start+1))
59+
return hash_value[start]
60+
61+
return dfs(0)
62+
63+
13. μ •μƒμ μœΌλ‘œ ν†΅κ³Όλ˜λŠ” 것 확인 μ™„λ£Œ
64+
"""
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
class Solution:
2+
def longestConsecutive(self, nums: list[int]) -> int:
3+
if not nums:
4+
return 0
5+
6+
nums_set = set(nums)
7+
max_length = 0
8+
9+
for num in nums_set:
10+
# μ‘°κΈ° μ’…λ£Œ: 남은 μˆ«μžλ³΄λ‹€ max_lengthκ°€ 크면 더 이상 λΆˆκ°€λŠ₯
11+
if max_length >= len(nums_set):
12+
break
13+
14+
# μˆ˜μ—΄μ˜ μ‹œμž‘μ μΈμ§€ 확인 (이전 값이 μ—†μ–΄μ•Ό 함)
15+
if num - 1 not in nums_set:
16+
current_num = num
17+
current_length = 1
18+
19+
# μ—°μ†λœ λ‹€μŒ μˆ«μžλ“€μ„ μ°Ύμ•„κ°€λ©° 길이 계산
20+
while current_num + 1 in nums_set:
21+
current_num += 1
22+
current_length += 1
23+
24+
max_length = max(max_length, current_length)
25+
26+
return max_length
27+
28+
"""
29+
================================================================================
30+
풀이 κ³Όμ •
31+
================================================================================
32+
33+
[문제 뢄석] 연속 μˆ˜μ—΄μ˜ μ΅œλŒ€ 길이 μ°ΎκΈ°
34+
────────────────────────────────────────────────────────────────────────────────
35+
1. 연속 μˆ˜μ—΄μ˜ 길이λ₯Ό λ°˜ν™˜ν•΄μ•Όν•˜λŠ”λ°
36+
2. O(n) μ‹œκ°„ 내에 λ™μž‘ν•˜λŠ” μ•Œκ³ λ¦¬μ¦˜μœΌλ‘œ λ§Œλ“€μ–΄μ•Όν•˜λ„€
37+
β†’ μ‹œκ°„μ„ 획기적으둜 μ€„μ—¬μ•Όν•˜λ‹ˆκΉŒ set을 μ‚¬μš©ν•˜λ©΄ μ’‹μœΌλ €λ‚˜?
38+
39+
40+
[κ΅¬ν˜„ μ „λž΅] 기쀀점 기반 탐색
41+
────────────────────────────────────────────────────────────────────────────────
42+
3. 연속 μˆ˜μ—΄μ΄λ‹ˆκΉŒ νŠΉμ • κΈ°μ€€μ μœΌλ‘œλΆ€ν„° + 1인 값이 μ–Όλ§ˆλ‚˜ λ°˜λ³΅λ˜λŠ”μ§€ μ΅œλŒ€ 길이λ₯Ό ꡬ해야겠닀.
43+
4. νŠΉμ • 기쀀점이 μ—¬λŸ¬ 번 λ°”λ€” μˆ˜λ„ μžˆλŠ”λ°, set으둜 쀑볡 제거λ₯Ό ν–ˆμœΌλ‹ˆκΉŒ 문제 없어보인닀.
44+
5. 기쀀점을 μˆ˜μ—΄μ˜ μˆ«μžκ°€ μ‹œμž‘ν•˜λŠ” μ‹œμ μœΌλ‘œ 작으렀면, μˆ˜μ—΄μ˜ 이전 값이 μ‘΄μž¬ν•˜μ§€ μ•Šμ•„μ•Όκ² λ„€
45+
46+
nums_set = set(nums)
47+
max_length = 0
48+
49+
for num in nums_set:
50+
if num - 1 not in nums_set: # μˆ˜μ—΄μ˜ μ‹œμž‘μ μΈ 경우만
51+
current = num
52+
length = 1
53+
54+
while current + 1 in nums_set:
55+
current += 1
56+
length += 1
57+
58+
max_length = max(max_length, length)
59+
60+
return max_length
61+
62+
6. 더 κ°œμ„ ν•  뢀뢄이 μžˆλ‚˜?
63+
7. Claudeμ—κ²Œ μ½”λ“œλ‘œ 질문
64+
8. Early Return 쑰건을 ν™œμš©ν•˜λΌκ³  λ‹΅λ³€ (배열이 μ—†λŠ” κ²½μš°μ™€ 남은 μˆ«μžλ³΄λ‹€ max_lengthκ°€ 더 큰 경우)
65+
66+
def longestConsecutive(self, nums: list[int]) -> int:
67+
if not nums:
68+
return 0
69+
70+
nums_set = set(nums)
71+
max_length = 0
72+
73+
for num in nums_set:
74+
# μ‘°κΈ° μ’…λ£Œ: 남은 μˆ«μžλ³΄λ‹€ max_lengthκ°€ 크면 더 이상 λΆˆκ°€λŠ₯
75+
if max_length >= len(nums_set):
76+
break
77+
78+
if num - 1 not in nums_set:
79+
current_num = num
80+
current_length = 1
81+
82+
while current_num + 1 in nums_set:
83+
current_num += 1
84+
current_length += 1
85+
86+
max_length = max(max_length, current_length)
87+
88+
return max_length
89+
"""
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from collections import Counter
2+
3+
4+
class Solution:
5+
def topKFrequent(self, nums: list[int], k: int) -> list[int]:
6+
nums_count = Counter(nums)
7+
return [key for key, _ in nums_count.most_common(k)]
8+
9+
"""
10+
================================================================================
11+
풀이 κ³Όμ •
12+
================================================================================
13+
14+
[1μ°¨ μ‹œλ„] Counter의 most_common() ν™œμš©
15+
────────────────────────────────────────────────────────────────────────────────
16+
1. k개의 λΉˆλ„κ°€ κ°€μž₯ 높은 μš”μ†Œ?
17+
2. Counter ν•¨μˆ˜λ₯Ό μ΄μš©ν•΄μ„œ K개 개수λ₯Ό μ„Έλ©΄ 될듯?
18+
19+
nums_count = Counter(nums)
20+
return [key for key, _ in nums_count.most_common(k)]
21+
22+
[μ„±λŠ₯ 뢄석]
23+
3. Counter.most_common() λ©”μ„œλ“œλŠ” λ‚΄λΆ€λŠ” μ–΄λ–»κ²Œ κ΅¬ν˜„λ˜μ–΄μžˆμ§€?
24+
25+
26+
def most_common(self, n=None):
27+
'''List the n most common elements and their counts from the most
28+
common to the least. If n is None, then list all element counts.
29+
30+
>>> Counter('abracadabra').most_common(3)
31+
[('a', 5), ('b', 2), ('r', 2)]
32+
33+
'''
34+
# Emulate Bag.sortedByCount from Smalltalk
35+
if n is None:
36+
return sorted(self.items(), key=_itemgetter(1), reverse=True)
37+
38+
# Lazy import to speedup Python startup time
39+
import heapq
40+
return heapq.nlargest(n, self.items(), key=_itemgetter(1))
41+
42+
4. n이 μ—†μœΌλ©΄ λͺ¨λ“  μš”μ†Œλ₯Ό λΉˆλ„μˆ˜ μˆœμ„œλŒ€λ‘œ λ°˜ν™˜
43+
5. Heap 기반 μ•Œκ³ λ¦¬μ¦˜μ„ μ‚¬μš©ν•˜κ³  μžˆλ„€? (Min Heap)
44+
6. _itemgetter(1)은 카운트λ₯Ό κΈ°μ€€μœΌλ‘œ μ •λ ¬ν•˜κΈ° μœ„ν•œ 것
45+
"""

β€Žtwo-sum/unpo88.pyβ€Ž

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
class Solution:
2+
def twoSum(self, nums: list[int], target: int) -> list[int]:
3+
num_to_index = {}
4+
5+
for i, num in enumerate(nums):
6+
diff = target - num
7+
8+
if diff in num_to_index:
9+
j = num_to_index[diff]
10+
return [i, j]
11+
12+
num_to_index[num] = i
13+
14+
"""
15+
================================================================================
16+
풀이 κ³Όμ •
17+
================================================================================
18+
19+
[1μ°¨ μ‹œλ„] Brute Force - O(n^2)
20+
────────────────────────────────────────────────────────────────────────────────
21+
1. λ‹¨μˆœ 반볡으둜 κ·Έλƒ₯ 문제λ₯Ό ν’€μ–΄λ³΄μž.
22+
2. 단 같은 숫자일 κ²½μš°μ—λŠ” λ„˜μ–΄κ°€μž.
23+
24+
for i in range(len(nums)):
25+
for j in range(len(nums)):
26+
if i == j:
27+
continue
28+
if nums[i] + nums[j] == target:
29+
return [i, j]
30+
31+
3. O(n^2) 으둜 문제λ₯Ό ν’€μ—ˆλŠ”λ°
32+
4. μ‹œκ°„μ΄ μ˜€λž˜κ±Έλ¦¬λ‹ˆκΉŒ λ‹€λ₯Έ 풀이 방법이 μžˆλŠ” 것 κ°™μŒ
33+
34+
35+
[2μ°¨ μ‹œλ„] Hash Table - Two Pass
36+
────────────────────────────────────────────────────────────────────────────────
37+
5. ν•΄μ‹±μœΌλ‘œ 문제λ₯Ό ν’€ 방법이 μžˆμœΌλ €λ‚˜?
38+
6. λ„˜λ²„λ§ˆλ‹€ 인덱슀λ₯Ό μ €μž₯ν•˜κ³ 
39+
7. targetμ—μ„œ ν˜„μž¬ κ°€μ§„ 값을 λΊ€ 값이 nums에 μžˆλŠ”μ§€λ₯Ό νŒλ‹¨ν•˜λ©΄ 될 것 같은데?
40+
8. 그리고 ν˜„μž¬ κ°€μ§„ κ°’κ³Ό λΊ€ κ°’μ˜ 인덱슀λ₯Ό κ·ΈλŒ€λ‘œ λ°˜ν™˜ν•˜λ©΄ 될 것 κ°™κ³ 
41+
9. 근데 λ™μΌν•œ μΈλ±μŠ€λŠ” μ œμ™Έν•΄μ•Όν• λ“―
42+
43+
num_index_dict = defaultdict()
44+
for index, num in enumerate(nums):
45+
num_index_dict[num]=index
46+
print(num_index_dict)
47+
48+
for index, num in enumerate(nums):
49+
if (target - num) in nums and num_index_dict[target - num] != index:
50+
return [index, num_index_dict[target-num]]
51+
52+
53+
[3μ°¨ μ‹œλ„] Hash Table - One Pass
54+
────────────────────────────────────────────────────────────────────────────────
55+
10. 단 ν•œ 번의 λ£¨ν”„μ—μ„œλ„ λ™μž‘μ‹œν‚¬ 수 μžˆμ„λ“―?
56+
57+
num_index_dict = defaultdict()
58+
59+
for index, num in enumerate(nums):
60+
if (target - num) in num_index_dict:
61+
return [index, num_index_dict[target - num]]
62+
63+
num_index_dict[num] = index
64+
65+
66+
[μ΅œμ’… κ°œμ„ ] μ½”λ“œ 가독성 ν–₯상
67+
────────────────────────────────────────────────────────────────────────────────
68+
11. 속도가 많이 λΉ¨λΌμ‘Œλ‹€. μ½”λ“œ κ°€λ…μ„±λ§Œ λ†’μ—¬λ³΄μž
69+
70+
num_to_index = {}
71+
72+
for i, num in enumerate(nums):
73+
diff = target - num
74+
75+
if diff in num_to_index:
76+
j = num_to_index[diff]
77+
return [i, j]
78+
79+
num_to_index[num] = i
80+
"""

0 commit comments

Comments
Β (0)