Skip to content

Commit 6e1a139

Browse files
authored
Merge pull request #2417 from liza0525/main
[liza0525] WEEK 02 solutions
2 parents 81ca178 + 5cdf1e1 commit 6e1a139

5 files changed

Lines changed: 155 additions & 0 deletions

File tree

3sum/liza0525.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,39 @@ def threeSum(self, nums: List[int]) -> List[List[int]]:
3636
results.add((nums[i], nums[left], nums[right]))
3737
left, right = left + 1, right - 1
3838
return list(results)
39+
40+
41+
# 7기 풀이
42+
# 시간 복잡도: O(n^2)
43+
# - 배열 정렬: O(n log n)
44+
# - for문과 while문을 이용한 이중 loop문으로 탐색: O(n^2)
45+
# - 전체 시간 복잡도는 O(n^2)
46+
# 공간 복잡도: O(1)
47+
# - 결과 저장 공간은 output이므로 제외 (변수 이름: results)
48+
class Solution:
49+
def threeSum(self, nums: List[int]) -> List[List[int]]:
50+
nums.sort() # 정렬을 한 번 한 후
51+
results = set()
52+
53+
# for 문과 투포인터를 이용해 문제를 푼다.
54+
for i in range(len(nums) - 2):
55+
# i번째와 i - 1 번째 값이 같은 경우에는 이미 이전 loop에서 계산했기 때문에 다음 루프로 넘긴다
56+
if i > 0 and nums[i] == nums[i - 1]:
57+
continue
58+
59+
# 포인터 지정
60+
left, right = i + 1, len(nums) - 1
61+
while left < right:
62+
result = nums[i] + nums[left] + nums[right]
63+
if result < 0:
64+
# 합이 0보다 작다면 요소의 값을 올려야 하기 때문에 left를 올린다. (nums는 정렬이 된 상태)
65+
left += 1
66+
elif result > 0:
67+
# 합이 0보다 크다면 요소의 값을 줄여야 하기 때문에 right를 내린다. (nums는 정렬이 된 상태)
68+
right -= 1
69+
else:
70+
# 합이 0이면 결과 저장 후, 포인터를 조정하여 다음 triplet 세트를 찾는다.
71+
results.add((nums[i], nums[left], nums[right]))
72+
left, right = left + 1, right - 1
73+
74+
return list(results)

climbing-stairs/liza0525.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,34 @@ def fibonacci(step):
1515
fibonacci(3)
1616

1717
return memo[n]
18+
19+
20+
# 7기 풀이
21+
# 시간 복잡도: O(n)
22+
# - memoization을 이용해 결과를 저장을 하면, 계산은 0 ~ n까지 한 번씩만 계산
23+
# - 즉, 계단의 개수 n이 최대 계산 횟수이므로 전체 연산은 O(n)
24+
# 공간 복잡도: O(n)
25+
# - memoization을 하기 위한 dict에 최대 n의 개수만큼만 저장
26+
# - 재귀 호출 스택 깊이도 최대 n
27+
class Solution:
28+
# 해당 문제는 이전 계단까지 계산된 경우의 수를 찾아가며 현재 계단까지 오를 수 있는 경우의 수를 계산한다.
29+
# n번째 계단까지 오를 수 있는 경우의 수는 (n-1번째까지 오를 수 있는 경우의 수) + (n-2번째까지 오를 수 있는 경우의 수)이다.
30+
# 이는 동적 프로그래밍을 이용해 memoization을 하며 풀 수 있는 문제라고 할 수 있다.
31+
def climbStairs(self, n: int) -> int:
32+
memo = {}
33+
34+
def dfs(n):
35+
# n이 0 또는 1일 경우에는 하나의 방법만 있기 때문에 memo에 1을 넣고 return해준다.
36+
if n <= 1:
37+
memo[n] = 1
38+
return memo[n]
39+
40+
# memoization을 이미한 경우에는 memo에서 결과를 꺼내 return해준다.
41+
if n in memo:
42+
return memo[n]
43+
44+
# (n번째까지 오를 수 있는 경우의 수) = (n-1번째까지 오를 수 있는 경우의 수) + (n-2번째까지 오를 수 있는 경우의 수)
45+
memo[n] = dfs(n - 1) + dfs(n - 2)
46+
return memo[n]
47+
48+
return dfs(n)

product-of-array-except-self/liza0525.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,32 @@ def productExceptSelf(self, nums: List[int]) -> List[int]:
2020
answers[i] *= after_total_prod
2121

2222
return answers
23+
24+
25+
# 7기 풀이
26+
# 시간 복잡도: O(n)
27+
# - nums의 길이만큼이 최대 연산 횟수가 된다. for문 두 번 돌린 것은 O(2n) -> O(n)으로 표기 가능
28+
# 공간 복잡도: O(n)
29+
# - nums의 길이만큼 res를 만든다.
30+
# - 단 이는 return variable이라서 리트코드에서는 공간 복잡도 계산에서 제외, 조건의 O(1)와 동일하다고 할 수 있다.
31+
class Solution:
32+
def productExceptSelf(self, nums: List[int]) -> List[int]:
33+
# 정답에 대한 리스트 추가
34+
res = [1 for _ in range(len(nums))]
35+
36+
previous_res = 1
37+
for i in range(len(nums)):
38+
# i번째 인덱싀 이전까지의 값들을 res[i]에 먼저 곱해준 후,
39+
# 자기 자신을 previous_res에 계산한다. 이는 다음 loop, 즉 i+1번째일 때 계산된 값을 그대로 곱하게 된다.
40+
res[i] *= previous_res
41+
previous_res *= nums[i]
42+
43+
next_res = 1
44+
for i in range(len(nums) -1, -1, -1):
45+
# 리스트의 맨 뒷쪽 index부터 계산해주면 i번째 인덱스 이후의 값들의 곱들을 계산할 수 있다.
46+
# i번째 인덱싀 이후까지의 값들을 res[i]에 먼저 곱해준 후,
47+
# 자기 자신을 next_res 계산한다. 이는 다음 loop, 즉 i-1번째일 때 계산된 값을 그대로 곱하게 된다.
48+
res[i] *= next_res
49+
next_res *= nums[i]
50+
51+
return res

valid-anagram/liza0525.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,34 @@ def isAnagram(self, s: str, t: str) -> bool:
2323
if cnt != 0:
2424
return False
2525
return True
26+
27+
28+
29+
# 7기 풀이
30+
# 시간 복잡도: O(n)
31+
# - s, t, letter_dict를 모두 한 loop당 한 번 씩만 돈다.
32+
# 공간 복잡도: O(n)
33+
# - letter_dict 생성 시 s의 길이(n이라고 할 때)에 종속된다.
34+
from collections import defaultdict
35+
36+
37+
class Solution:
38+
def isAnagram(self, s: str, t: str) -> bool:
39+
# s를 구성하는 각 알파벳의 개수를 저장할 defaultdict을 생성
40+
letter_dict = defaultdict(int)
41+
42+
# s의 문자열을 돌며 각 알파벳의 개수를 카운트
43+
for ss in s:
44+
letter_dict[ss] += 1
45+
46+
# t 문자열을 돌만셔 각 알파벳의 개수만큼 dictionary에서 빼준다.
47+
for tt in t:
48+
letter_dict[tt] -= 1
49+
50+
# s, t를 돌며 각 알파벳의 개수를 센 후 value들은 모두 0이 되어야 한다. (아나그램 특성 상)
51+
# 각 알파벳의 value가 양수면 s에 더 많았고, 음수면 t가 더 많았다는 의미가 됨
52+
for v in letter_dict.values():
53+
if v != 0:
54+
return False
55+
56+
return True

validate-binary-search-tree/liza0525.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,31 @@ def inorder_tree(tree_node):
2020
return False
2121

2222
return True
23+
24+
25+
# 7기 풀이
26+
# 시간 복잡도: O(n)
27+
# - 전체 트리 노드를 탐색하기 때문에 n
28+
# 공간 복잡도: O(n)
29+
# - 노드를 저장하는 리스트는 n의 길이만큼 생김
30+
class Solution:
31+
# 중위 순회 결과가 strictly increasing인지 확인하는 방식
32+
def isValidBST(self, root: Optional[TreeNode]) -> bool:
33+
tree_res = []
34+
35+
def inorder_search(node):
36+
if node.left:
37+
inorder_search(node.left)
38+
39+
tree_res.append(node.val)
40+
41+
if node.right:
42+
inorder_search(node.right)
43+
44+
inorder_search(root)
45+
46+
for i in range(len(tree_res) - 1):
47+
# i번째 값이 i + 1번째 값보다 크거나 같으면 strictly increasing하지 않다는 의미이므로 False를 리턴한다.
48+
if tree_res[i] >= tree_res[i + 1]:
49+
return False
50+
return True

0 commit comments

Comments
 (0)