Skip to content

Commit 649342d

Browse files
authored
Merge pull request #1750 from wozlsla/main
[wozlsla] WEEK 02 solutions
2 parents 0158a69 + 1c8b007 commit 649342d

File tree

5 files changed

+396
-0
lines changed

5 files changed

+396
-0
lines changed

3sum/wozlsla.py

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
"""
2+
# Intuition
3+
-
4+
5+
# Approach
6+
index가 모두 다를것,
7+
합 = 0 -> -a = b+c
8+
중복 X -> set : dic와 다르게 가변객체 삽입 X
9+
Two Pointer -> 정렬된 배열을 활용
10+
11+
# Complexity
12+
- Time complexity
13+
- Brute-force : O(N^3)
14+
- Set : O(N^2) - Time Limit Exceeded (memory??)
15+
- Two Pointer : O(N^2)
16+
17+
- Space complexity
18+
- Brute-force : O(N)
19+
- Set : O(N)
20+
- Two Pointer : O(1)
21+
"""
22+
23+
from typing import List
24+
25+
26+
class Solution:
27+
def threeSum(self, nums: List[int]) -> List[List[int]]:
28+
29+
triplets = set()
30+
nums.sort() # O(NlogN), return None
31+
32+
for i in range(len(nums) - 2): # O(N)
33+
low, high = i + 1, len(nums) - 1
34+
35+
while low < high: # O(N)
36+
three_sum = nums[i] + nums[low] + nums[high]
37+
38+
if three_sum < 0:
39+
low += 1
40+
elif three_sum > 0:
41+
high -= 1
42+
else:
43+
triplets.add((nums[i], nums[low], nums[high]))
44+
low, high = low + 1, high - 1
45+
46+
return list(triplets)
47+
48+
49+
""" Set
50+
class Solution:
51+
def threeSum(self, nums: List[int]) -> List[List[int]]:
52+
53+
triplets = set()
54+
55+
for i in range(len(nums) - 2):
56+
seen = set()
57+
58+
for j in range(i + 1, len(nums)):
59+
complement = -(nums[i] + nums[j])
60+
61+
if complement in seen:
62+
triplets.add(tuple(sorted([nums[i], nums[j], complement])))
63+
64+
seen.add(nums[j])
65+
66+
return list(triplets)
67+
"""
68+
69+
""" Brute-force
70+
class Solution:
71+
def threeSum(self, nums: List[int]) -> List[List[int]]:
72+
73+
n = len(nums)
74+
result = []
75+
76+
for i in range(n-2):
77+
for j in range(i+1, n-1):
78+
for k in range(j+1, n):
79+
if i != j and i != k and j != k:
80+
81+
if nums[i] + nums[j] + nums[k] == 0:
82+
li = sorted([nums[i], nums[j], nums[k]])
83+
84+
if li not in result: # O(L)
85+
result.append(li)
86+
87+
return result
88+
"""
89+
90+
nums = [-1, 0, 1, 2, -1, -4]
91+
sol = Solution()
92+
93+
print(sol.threeSum(nums))
94+
# [[-1,-1,2],[-1,0,1]]
95+
96+
# print(len({1, 1, 2})) # 2

climbing-stairs/wozlsla.py

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
"""
2+
# Intuition
3+
계단 정상에 오를 수 있는 방법의 수 - 1,2 - 순열? -> X. 자리수가 일정하지 않음
4+
5+
# Approach
6+
접근 1) 1 or 2 로만 이동 가능
7+
8+
풀이 참고
9+
- 계단을 한 번에 최대 2칸 밖에 올라갈 수 없으므로, 3번째 칸에 발을 딛기 위해서는 바로 아래 칸인 2번째 칸이나 적어도 1번째 칸에 반드시 먼저 올라와있어야 함.
10+
- 즉, n 칸에 발을 딛기위해서는 그 전에 n - 1 칸이나 n - 2 칸까지 올라와왔어야 한다.
11+
12+
접근 2)
13+
4 -> 5
14+
1 1 1 1
15+
2 1 1
16+
1 2 1
17+
1 1 2
18+
2 2
19+
20+
5 -> 8
21+
1 1 1 1 1
22+
2 2 1
23+
1 2 2
24+
2 1 2
25+
1 1 1 2
26+
1 1 2 1
27+
1 2 1 1
28+
2 1 1 1
29+
30+
n=5까지만 봤을 때 늘어나는 규칙이 피보나치수열과 같음. (hint)
31+
32+
# Complexity
33+
- Time complexity
34+
- DP 1 : O(N)
35+
- DP 2 : O(N)
36+
37+
- Recursive 1 : O(2^N)
38+
- Recursive 2 (caching): O(N)
39+
40+
- Space complexity
41+
- DP 1 : O(N)
42+
- DP 2 : O(1)
43+
44+
- Recursive 1 : O(N)
45+
- Recursive 2 (caching): O(N)
46+
47+
"""
48+
49+
50+
# DP 2 (공간 최적화)
51+
class Solution:
52+
def climbStairs(self, n: int) -> int:
53+
54+
if n < 3:
55+
return n
56+
57+
pre, cur = 1, 2
58+
59+
for _ in range(n - 2):
60+
pre, cur = cur, pre + cur # 순서 !
61+
62+
return cur
63+
64+
65+
""" DP 1
66+
class Solution:
67+
def climbStairs(self, n: int) -> int:
68+
69+
dp = {1:1, 2:2}
70+
71+
for i in range(3, n+1):
72+
dp[i] = dp[i-1] + dp[i-2]
73+
74+
return dp[n]
75+
"""
76+
77+
""" Memoization (재귀 + 캐싱)
78+
class Solution:
79+
def climbStairs(self, n: int) -> int:
80+
memo = {}
81+
82+
def _climb(n):
83+
84+
if n not in memo:
85+
if n < 3:
86+
memo[n] = n
87+
else:
88+
memo[n] = _climb(n - 1) + _climb(n - 2)
89+
90+
return memo[n]
91+
92+
return _climb(n)
93+
"""
94+
95+
96+
""" Recursive
97+
class Solution:
98+
def climbStairs(self, n: int) -> int:
99+
100+
if n < 3:
101+
return n
102+
103+
return self.climbStairs(n-1) + self.climbStairs(n-2)
104+
"""

house-robber/wozlsla.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"""
2+
# Intuition
3+
<!-- Describe your first thoughts on how to solve this problem. -->
4+
5+
# Approach
6+
<!-- Describe your approach to solving the problem. -->
7+
8+
# Complexity
9+
- Time complexity:
10+
11+
- Space complexity:
12+
13+
"""
14+
15+
16+
# DP
17+
class Solution:
18+
def rob(self, nums: List[int]) -> int:
19+
20+
# initialize dp array
21+
dp = [0] * (len(nums) + 1)
22+
23+
if nums:
24+
dp[1] = nums[0]
25+
26+
for n in range(2, len(dp)):
27+
# current house : nums[n-1]
28+
rob_current = nums[n - 1] + dp[n - 2]
29+
skip_current = dp[n - 1]
30+
31+
dp[n] = max(rob_current, skip_current)
32+
33+
return dp[-1]
34+
35+
36+
""" Recursive + Memoization
37+
class Solution:
38+
def rob(self, nums: List[int]) -> int:
39+
40+
memo = {}
41+
42+
def dfs(start):
43+
if start in memo:
44+
return memo[start]
45+
46+
if start >= len(nums):
47+
memo[start] = 0
48+
else:
49+
memo[start] = max(nums[start] + dfs(start + 2), dfs(start + 1))
50+
51+
return memo[start]
52+
53+
return dfs(0)
54+
"""
55+
56+
""" Recursive
57+
class Solution:
58+
def rob(self, nums: List[int]) -> int:
59+
60+
def dfs(start):
61+
if start >= nums(len):
62+
return 0
63+
64+
return max(nums[start] + dfs[start+2], dfs[start+1])
65+
66+
return dfs(0)
67+
"""
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
"""
2+
# Intuition
3+
하나씩 순회하면서 나머지 값들을 곱함
4+
5+
# Approach
6+
접근 1) 원형 큐를 사용하면?
7+
현재 제외하려는 요소를 popleft()로 제거하고, 나머지 요소들의 곱을 계산한 뒤, 다시 그 요소를 append()하여 다음 반복을 위해 덱의 순서를 회전
8+
9+
접근 2)
10+
1 b c d --> 1 x bcd
11+
a 1 c d --> a x cd
12+
a b 1 d --> ab x d
13+
a b c 1 --> abc x 1
14+
15+
16+
# Complexity
17+
- Time complexity : O(N)
18+
- Space complexity : O(N) / O(1)
19+
"""
20+
21+
from typing import List
22+
23+
24+
class Solution:
25+
def productExceptSelf(self, nums: List[int]) -> List[int]:
26+
27+
n = len(nums)
28+
res = [1] * n
29+
30+
prefix_product = 1
31+
for i in range(n):
32+
res[i] = prefix_product
33+
prefix_product *= nums[i]
34+
35+
suffix_product = 1
36+
for i in range(n - 1, -1, -1):
37+
res[i] *= suffix_product
38+
suffix_product *= nums[i]
39+
40+
41+
"""
42+
class Solution:
43+
def productExceptSelf(self, nums: List[int]) -> List[int]:
44+
45+
# 중복 계산을 피하는 방법?
46+
res_1 = [1] * len(nums)
47+
res_2 = [1] * len(nums)
48+
49+
for n in range(1, len(nums)): # [1, 1(a), 2(ab), 6(abc)]
50+
res_1[n] = res_1[n - 1] * nums[n - 1]
51+
52+
# reverse X -> range를 반대로
53+
for n in range(len(nums) - 1, -1, -1): # [1, 4(d), 12(cd), 24(bcd)]
54+
res_2[n] = res_2[n + 1] * nums[n + 1]
55+
56+
res_2.reverse()
57+
return [res_1[i] * res_2[i] for i in range(len(nums))]
58+
59+
60+
sol = Solution()
61+
print(sol.productExceptSelf([1, 2, 3, 4]))
62+
"""
63+
64+
65+
"""
66+
# deque : O(N^2)
67+
from collections import deque
68+
import math
69+
70+
class Solution:
71+
def productExceptSelf(self, nums: List[int]) -> List[int]:
72+
73+
nums = deque(nums)
74+
result = []
75+
76+
for _ in range(len(nums)): # O(N)
77+
tmp = nums.popleft()
78+
result.append(math.prod(nums)) # O(N)
79+
nums.append(tmp)
80+
81+
return result
82+
"""

0 commit comments

Comments
 (0)