Skip to content

Commit fddc0cc

Browse files
authored
Merge pull request DaleStudy#2449 from liza0525/main
[liza0525] WEEK 03 solutions
2 parents 14f12c8 + d433b66 commit fddc0cc

5 files changed

Lines changed: 146 additions & 0 deletions

File tree

combination-sum/liza0525.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,42 @@ def dfs(target_list, start_i):
3838
dfs([], 0)
3939

4040
return results
41+
42+
43+
# 7기 풀이
44+
# T: target 수, C: candidates의 최소값일 때,
45+
# 시간 복잡도: O(n ^ (T/C))
46+
# - 최악의 경우는 가장 작은 candidate로 target을 만드는 횟수만큼 candidates를 탐색할 때이다. (dominant)
47+
# - sorting은 O(n log n)이며, 무시 가능
48+
# 공간 복잡도: O(T/C)
49+
# - dfs의 call stack의 깊이는 T/C가 최대 깊이
50+
# - result의 조합 또한 T/C가 최대 길이
51+
class Solution:
52+
# DFS로 문제를 풀이하며 조건에 맞춰 가지치기가 필요한 문제
53+
# 문제 풀이 편의를 위해 candidates를 sorting한 후 풀이를 한다.
54+
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
55+
candidates.sort()
56+
results = []
57+
58+
def dfs(target, result):
59+
if target == 0:
60+
# 더이상 target을 만드는데 숫자가 필요하지 않으므로
61+
# 정답 array에 deepcopy하여 저장
62+
results.append(result[:])
63+
return
64+
65+
for candidate in candidates:
66+
if candidate > target:
67+
# 후보 수가 target보다 크면 그 이후의 수는 더이상 탐색하지 않아도 된다
68+
return
69+
if result and candidate < result[-1]:
70+
# 후보 수가 result의 마지막 수보다 크면 skip한다(result 내 숫자들도 작은 수부터 저장되게 함)
71+
continue
72+
result.append(candidate)
73+
# target에서 candidate를 뺀 만큼 다음 stack 계산을 한다.
74+
dfs(target - candidate, result)
75+
result.pop()
76+
77+
dfs(target, [])
78+
79+
return results

decode-ways/liza0525.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# 7기 풀이
2+
# 시간복잡도: O(n)
3+
# - memoization을 하기 때문에 각 인덱스 별로 가능한 수를 계산할 때 한 번 씩만 계산
4+
# 공간복잡도: O(n)
5+
# - 문자열의 길이만큼 memo 값이 늘어남
6+
class Solution:
7+
# DP를 이용해 문제를 풀면 된다.
8+
# 각 인덱스로 별로 문자열을 잘랐을 때의 가능한 디코딩 방법 수를 memo한다
9+
def numDecodings(self, s: str) -> int:
10+
len_s = len(s)
11+
memo = {}
12+
13+
def dfs(index):
14+
if index == len_s: # 끝까지 탐색했다면 가능한 디코딩 방법이므로 1을 return
15+
return 1
16+
17+
if s[index] == '0': # 현재 index의 문자가 '0'이면 해당 방법은 디코딩이 불가한 것으로 판단 0을 return
18+
return 0
19+
20+
if index in memo: # 이미 저장되어 있다면 memo 값을 return
21+
return memo[index]
22+
23+
result = dfs(index + 1) # index로부터 한 자리 수만 계산할 때, 다음 계산은 index + 1이 된다
24+
25+
if (
26+
index + 1 < len_s
27+
and int(s[index:index + 2]) <= 26
28+
): # index~index+1의 문자열이 26보다 작은 두 자리 수일 때만 index + 2번째 계산을 한다
29+
result += dfs(index + 2)
30+
31+
memo[index] = result # memoization을 한다
32+
return result
33+
34+
return dfs(0)

maximum-subarray/liza0525.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# 7기 풀이
2+
# 시간 복잡도: O(n)
3+
# - nums의 모든 요소를 탐색하기 때문에 nums의 길이에 관련되어 있음
4+
# 공간 복잡도: O(1)
5+
# - 변수 이외에 객체를 쓰지 않았기 때문에 공간 복잡도는 O(1)이다(input 길이와 상관 없음)
6+
class Solution:
7+
def maxSubArray(self, nums: List[int]) -> int:
8+
curr_sum = nums[0]
9+
max_sum = nums[0]
10+
11+
for i in range(1, len(nums)):
12+
# 1. (현재까지의 합과 i의 요소를 더한 값)과 i의 요소를 서로 비교하여 지금까지의 합을 업데이트한다.
13+
# - 자기 자신만으로도 이전 합들보다 크다면 이전 합들은 의미가 없어짐을 얘기
14+
curr_sum = max(nums[i], curr_sum + nums[i])
15+
16+
# 현재까지의 합과 이전 max 합을 비교하여 업데이트
17+
max_sum = max(max_sum, curr_sum)
18+
19+
return max_sum

number-of-1-bits/liza0525.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,27 @@ def hammingWeight(self, n: int) -> int:
2020
n = n // 2
2121

2222
return bits_sum
23+
24+
25+
# 7기 풀이
26+
# 시간 복잡도: O(log n)
27+
# - 2로 계속 나누고, 이는 2진수 자릿수 만큼 반복
28+
# 공간 복잡도: O(1)
29+
# - 고정된 변수(quotient, remainder)만 사용
30+
class Solution:
31+
def hammingWeight(self, n: int) -> int:
32+
# 10진수를 2진수로 변환하는 과정은 2로 계속 나누면서 그 나머지 값들을 순차적으로 나열하는 것이다.
33+
# 이 때 문자열로 만들지 않고 바로 result에 더해가면 답이 될 수 있음
34+
result = 0
35+
36+
while n > 0:
37+
# 몫과 나머지 계산
38+
quotient, remainder = n // 2, n % 2
39+
40+
# 나머지는 result에 더함
41+
result += remainder
42+
43+
# 몫은 다음 피제수로 사용
44+
n = quotient
45+
46+
return result

valid-palindrome/liza0525.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,33 @@ def isPalindrome(self, s: str) -> bool:
2424
return False
2525

2626
return True
27+
28+
29+
# 7기 풀이
30+
# 시간 복잡도: O(n)
31+
# - 문자열 s의 전체 문자를 순회할 때 길이 n만큼의 시간 소요
32+
# 공간 복잡도: O(1)
33+
# - start, end 등의 변수만 사용
34+
35+
class Solution:
36+
def isPalindrome(self, s: str) -> bool:
37+
# two pointer로 각 문자열을 비교하며 palindrome인지 체크한다.
38+
# 해당 문제의 조건 중 하나가 alphanumeric한 문자만 체크하는 것
39+
start, end = 0, len(s) - 1
40+
41+
# 양 끝의 포인터 인덱스가 같아지기 전까지 루프를 돌린다.
42+
while start < end:
43+
if not s[start].isalnum():
44+
# s[start] 문자가 alphanumeric하지 않은 경우엔 start 포인터를 오른쪽으로 한 칸 이동
45+
start += 1
46+
continue
47+
if not s[end].isalnum():
48+
# s[end] 문자가 alphanumeric하지 않은 경우엔 end 포인터를 왼쪽으로 한 칸 이동
49+
end -= 1
50+
continue
51+
if s[start].lower() != s[end].lower():
52+
# 두 문자의 lowercase가 동일하지 않은 경우에는 palindrome이 아니므로 False로 early return 해준다.
53+
return False
54+
start, end = start + 1, end - 1
55+
# while 루프가 다 돌았다면 조건에 걸리지 않고 palindrome임을 충족하므로 True를 return
56+
return True

0 commit comments

Comments
 (0)