Skip to content

Commit 2c92127

Browse files
authoredOct 4, 2024
Merge pull request #507 from lymchgmk/week8
[EGON] Week8 Solutions
2 parents 33741a7 + 4f95930 commit 2c92127

File tree

5 files changed

+270
-0
lines changed

5 files changed

+270
-0
lines changed
 

β€Žclone-graph/EGON.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
from typing import Optional, TypeVar
2+
from unittest import TestCase, main
3+
4+
5+
# Definition for a Node.
6+
class Node:
7+
def __init__(self, val = 0, neighbors = None):
8+
self.val = val
9+
self.neighbors = neighbors if neighbors is not None else []
10+
11+
12+
class Solution:
13+
def cloneGraph(self, node: Optional[Node]) -> Optional[Node]:
14+
return self.solve(node)
15+
16+
"""
17+
Runtime: 42 ms (Beats 45.48%)
18+
Time Complexity: O(n)
19+
20+
Memory: 17.04 (Beats 8.15%)
21+
Space Complexity: O(n), upper bound
22+
"""
23+
def solve(self, node: Optional[Node]) -> Optional[Node]:
24+
clone_dict = {}
25+
stack = [node]
26+
visited = set()
27+
while stack:
28+
curr_node = stack.pop()
29+
visited.add(curr_node.val)
30+
if curr_node.val not in clone_dict:
31+
clone_dict[curr_node.val] = Node(val=curr_node.val)
32+
33+
for neighbor in curr_node.neighbors:
34+
if neighbor.val not in clone_dict:
35+
clone_dict[neighbor.val] = Node(val=neighbor.val)
36+
37+
if neighbor.val not in visited:
38+
clone_dict[curr_node.val].neighbors.append(clone_dict[neighbor.val])
39+
clone_dict[neighbor.val].neighbors.append(clone_dict[curr_node.val])
40+
stack.append(neighbor)
41+
42+
return clone_dict[node.val]
43+
44+
45+
class _LeetCodeTestCases(TestCase):
46+
def test_1(self):
47+
node_dict = {1: Node(1), 2: Node(2), 3: Node(3), 4: Node(4)}
48+
node_dict[1].neighbors = [node_dict[2], node_dict[4]]
49+
node_dict[2].neighbors = [node_dict[1], node_dict[3]]
50+
node_dict[3].neighbors = [node_dict[2], node_dict[4]]
51+
node_dict[4].neighbors = [node_dict[1], node_dict[3]]
52+
53+
Solution.cloneGraph(Solution(), node_dict[1])
54+
self.assertTrue("RUN")
55+
56+
57+
if __name__ == '__main__':
58+
main()

β€Žlongest-common-subsequence/EGON.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from unittest import TestCase, main
2+
3+
4+
class Solution:
5+
def longestCommonSubsequence(self, text1: str, text2: str) -> int:
6+
return self.solve_dp(text1, text2)
7+
8+
"""
9+
Runtime: 441 ms (Beats 85.60%)
10+
Time Complexity: O(m * n)
11+
- text1, text2의 길이λ₯Ό 각각 m, n이라 ν•˜λ©΄ 이쀑 forλ¬Έ μ‘°νšŒμ— O(m * n)
12+
- i. dp λ°°μ—΄ κ°’ κ°±μ‹ μ—μ„œ κΈ°μ‘΄κ°’ +1에 O(1)
13+
- ii. dp λ°°μ—΄ κ°’ κ°±μ‹ μ—μ„œ 2개 항에 λŒ€ν•œ max 연산에 O(2), upper bound
14+
> O(m * n) * O(2) ~= O(m * n)
15+
16+
Memory: 41.81 (Beats 55.93%)
17+
Space Complexity: O(m * n)
18+
> row의 길이가 n이가 col의 길이가 m인 2차원 λ°°μ—΄ dp μ‚¬μš©μ— O(m * n)
19+
"""
20+
def solve_dp(self, text1: str, text2: str) -> int:
21+
dp = [[0] * (len(text2) + 1) for _ in range(len(text1) + 1)]
22+
for idx1 in range(len(text1)):
23+
for idx2 in range(len(text2)):
24+
if text1[idx1] == text2[idx2]:
25+
dp[idx1 + 1][idx2 + 1] = dp[idx1][idx2] + 1
26+
else:
27+
dp[idx1 + 1][idx2 + 1] = max(dp[idx1 + 1][idx2], dp[idx1][idx2 + 1])
28+
29+
return dp[-1][-1]
30+
31+
32+
class _LeetCodeTestCases(TestCase):
33+
def test_1(self):
34+
text1 = "abcde"
35+
text2 = "ace"
36+
output = 3
37+
self.assertEqual(
38+
Solution().longestCommonSubsequence(text1, text2),
39+
output
40+
)
41+
42+
43+
if __name__ == '__main__':
44+
main()
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
from unittest import TestCase, main
2+
from collections import defaultdict
3+
4+
5+
class Solution:
6+
def characterReplacement(self, s: str, k: int) -> int:
7+
return self.solve_sliding_window(s, k)
8+
9+
"""
10+
Runtime: 63 ms (Beats 98.40%)
11+
Time Complexity: O(n)
12+
- s에 λŒ€ν•΄ μ‘°νšŒν•˜λŠ”λ° O(n)
13+
- dict인 counterλ₯Ό μ‚¬μš©ν•΄μ„œ νŠΉμ • 문자의 λΉˆλ„μˆ˜ 체크, λΆ„κΈ°μ²˜λ¦¬, most_common_char 갱신에 O(1)
14+
- ν˜„μž¬ 졜μž₯ 길이 계산에 int κ³„μ‚°λ§Œ μ‚¬μš©ν•˜λ―€λ‘œ O(1)
15+
> O(n) * O(1) ~= O(n)
16+
17+
Memory: 16.54 (Beats 76.70%)
18+
Space Complexity: O(n), upper bound
19+
- left, right 같은 int 인덱슀 λ³€μˆ˜ 할당에 O(1)
20+
- most_common_char같은 str λ³€μˆ˜ 할당에 O(1)
21+
- dict인 counter의 μ΅œλŒ€ ν¬κΈ°λŠ” s의 λͺ¨λ“  λ¬Έμžκ°€ λ‹€λ₯΄κ³  k의 크기가 len(s)인 κ²½μš°μ΄λ―€λ‘œ O(n), upper bound
22+
> O(n), upper bound
23+
"""
24+
def solve_sliding_window(self, s: str, k: int) -> int:
25+
left = right = 0
26+
counter, most_common_char = defaultdict(int), ""
27+
for right in range(len(s)):
28+
counter[s[right]] += 1
29+
if counter[most_common_char] < counter[s[right]]:
30+
most_common_char = s[right]
31+
32+
if (right - left + 1) - counter[most_common_char] > k:
33+
counter[s[left]] -= 1
34+
left += 1
35+
36+
return right - left + 1
37+
38+
39+
class _LeetCodeTestCases(TestCase):
40+
def test_1(self):
41+
s = "AABBCC"
42+
k = 2
43+
output = 4
44+
self.assertEqual(Solution.characterReplacement(Solution(), s, k), output)
45+
46+
47+
if __name__ == '__main__':
48+
main()

β€Žmerge-two-sorted-lists/EGON.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from typing import Optional
2+
from unittest import TestCase, main
3+
4+
5+
class ListNode:
6+
def __init__(self, val=0, next=None):
7+
self.val = val
8+
self.next = next
9+
10+
11+
class Solution:
12+
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
13+
return self.solve(list1, list2)
14+
15+
"""
16+
Runtime: 36 ms (Beats 71.91%)
17+
Time Complexity: O(m + n)
18+
> list1의 길이λ₯Ό m, list2의 길이λ₯Ό n이라 ν•  λ•Œ, list1κ³Ό list2 λͺ¨λ‘ λκΉŒμ§€ μ‘°νšŒν•˜λ―€λ‘œ O(n + m)
19+
20+
Memory: 16.62 (Beats 37.59%)
21+
Space Complexity: O(m + n)
22+
> result의 κΈΈμ΄λŠ” list1의 길이와 list2의 길이의 ν•©κ³Ό κ°™μœΌλ―€λ‘œ O(m + n)
23+
"""
24+
def solve(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
25+
result = ListNode()
26+
node = result
27+
while list1 or list2:
28+
if list1 and list2:
29+
if list1.val < list2.val:
30+
node.next = list1
31+
node = node.next
32+
list1 = list1.next
33+
else:
34+
node.next = list2
35+
node = node.next
36+
list2 = list2.next
37+
38+
elif list1 and not list2:
39+
node.next = list1
40+
node = node.next
41+
list1 = list1.next
42+
43+
elif not list1 and list2:
44+
node.next = list2
45+
node = node.next
46+
list2 = list2.next
47+
48+
else:
49+
break
50+
51+
return result.next
52+
53+
54+
class _LeetCodeTestCases(TestCase):
55+
def test_1(self):
56+
list1 = ListNode(
57+
val=1,
58+
next=ListNode(
59+
val=2,
60+
next=ListNode(
61+
val=4
62+
)
63+
)
64+
)
65+
list2 = ListNode(
66+
val=1,
67+
next=ListNode(
68+
val=3,
69+
next=ListNode(
70+
val=4
71+
)
72+
)
73+
)
74+
output = [1,1,2,3,4,4]
75+
self.assertEqual(Solution.mergeTwoLists(Solution(), list1, list2), output)
76+
77+
78+
if __name__ == '__main__':
79+
main()

β€Žsum-of-two-integers/EGON.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from unittest import TestCase, main
2+
3+
4+
class Solution:
5+
def getSum(self, a: int, b: int) -> int:
6+
return self.solve_bit(a, b)
7+
8+
"""
9+
Runtime: 26 ms (Beats 94.94%)
10+
Time Complexity: O(log max(a, b)) ~= O(1)
11+
- a와 bλ₯Ό and μ—°μ‚° ν›„ μ™Όμͺ½μœΌλ‘œ shiftν•œ 값을 b에 ν• λ‹Ήν•˜λŠ”λ° λͺ¨λ‘ λΉ„νŠΈμ—°μ‚°μ΄λ―€λ‘œ O(1)
12+
- b의 값이 μ™Όμͺ½ shift에 μ˜ν•΄ κ°μ†Œν•˜λ―€λ‘œ log(b)
13+
- 단 b의 값은 a & b에 μ˜ν•΄ κ²°μ •λ˜λ―€λ‘œ log max(a, b)
14+
- μ „μ œ μ‘°κ±΄μ—μ„œ a, bλŠ” λͺ¨λ‘ μ ˆλŒ€κ°’ 1000 μ΄ν•˜μ˜ κ°’μ΄λ―€λ‘œ, μ΅œλŒ€ 10회의 shift μ—°μ‚°λ§Œ λ°œμƒν•˜λ―€λ‘œ, O(10) ~= O(1)
15+
> O(log max(a, b)) < O(10) ~= O(1)
16+
17+
Memory: 16.52 (Beats 18.98%)
18+
Space Complexity: O(1)
19+
> input에 λ¬΄κ΄€ν•˜κ²Œ μ •μˆ˜ν˜• λ³€μˆ˜λ“€λ§Œ μ‚¬μš©ν•˜λ―€λ‘œ O(1)
20+
"""
21+
def solve_bit(self, a: int, b: int) -> int:
22+
COMPLEMENT_MASK = 0xFFF
23+
24+
while b != 0:
25+
carry = a & b
26+
a = (a ^ b) & COMPLEMENT_MASK
27+
b = (carry << 1) & COMPLEMENT_MASK
28+
29+
return a if a <= 0x7FF else ~(a ^ COMPLEMENT_MASK)
30+
31+
32+
class _LeetCodeTestCases(TestCase):
33+
def test_1(self):
34+
a = -1
35+
b = 1
36+
output = 0
37+
self.assertEqual(Solution().getSum(a, b), output)
38+
39+
40+
if __name__ == '__main__':
41+
main()

0 commit comments

Comments
 (0)
Please sign in to comment.