Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions combination-sum/liza0525.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,42 @@ def dfs(target_list, start_i):
dfs([], 0)

return results


# 7기 풀이
# T: target 수, C: candidates의 최소값일 때,
# 시간 복잡도: O(n ^ (T/C))
# - 최악의 경우는 가장 작은 candidate로 target을 만드는 횟수만큼 candidates를 탐색할 때이다. (dominant)
# - sorting은 O(n log n)이며, 무시 가능
# 공간 복잡도: O(T/C)
# - dfs의 call stack의 깊이는 T/C가 최대 깊이
# - result의 조합 또한 T/C가 최대 길이
class Solution:
# DFS로 문제를 풀이하며 조건에 맞춰 가지치기가 필요한 문제
# 문제 풀이 편의를 위해 candidates를 sorting한 후 풀이를 한다.
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
candidates.sort()
results = []

def dfs(target, result):
if target == 0:
# 더이상 target을 만드는데 숫자가 필요하지 않으므로
# 정답 array에 deepcopy하여 저장
results.append(result[:])
return

for candidate in candidates:
if candidate > target:
# 후보 수가 target보다 크면 그 이후의 수는 더이상 탐색하지 않아도 된다
return
if result and candidate < result[-1]:
# 후보 수가 result의 마지막 수보다 크면 skip한다(result 내 숫자들도 작은 수부터 저장되게 함)
continue
result.append(candidate)
# target에서 candidate를 뺀 만큼 다음 stack 계산을 한다.
dfs(target - candidate, result)
result.pop()

dfs(target, [])

return results
34 changes: 34 additions & 0 deletions decode-ways/liza0525.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# 7기 풀이
# 시간복잡도: O(n)
# - memoization을 하기 때문에 각 인덱스 별로 가능한 수를 계산할 때 한 번 씩만 계산
# 공간복잡도: O(n)
# - 문자열의 길이만큼 memo 값이 늘어남
class Solution:
# DP를 이용해 문제를 풀면 된다.
# 각 인덱스로 별로 문자열을 잘랐을 때의 가능한 디코딩 방법 수를 memo한다
def numDecodings(self, s: str) -> int:
len_s = len(s)
memo = {}

def dfs(index):
if index == len_s: # 끝까지 탐색했다면 가능한 디코딩 방법이므로 1을 return
return 1

if s[index] == '0': # 현재 index의 문자가 '0'이면 해당 방법은 디코딩이 불가한 것으로 판단 0을 return
return 0

if index in memo: # 이미 저장되어 있다면 memo 값을 return
return memo[index]

result = dfs(index + 1) # index로부터 한 자리 수만 계산할 때, 다음 계산은 index + 1이 된다

if (
index + 1 < len_s
and int(s[index:index + 2]) <= 26
): # index~index+1의 문자열이 26보다 작은 두 자리 수일 때만 index + 2번째 계산을 한다
result += dfs(index + 2)

memo[index] = result # memoization을 한다
return result

return dfs(0)
19 changes: 19 additions & 0 deletions maximum-subarray/liza0525.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# 7기 풀이
# 시간 복잡도: O(n)
# - nums의 모든 요소를 탐색하기 때문에 nums의 길이에 관련되어 있음
# 공간 복잡도: O(1)
# - 변수 이외에 객체를 쓰지 않았기 때문에 공간 복잡도는 O(1)이다(input 길이와 상관 없음)
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
curr_sum = nums[0]
max_sum = nums[0]

for i in range(1, len(nums)):
# 1. (현재까지의 합과 i의 요소를 더한 값)과 i의 요소를 서로 비교하여 지금까지의 합을 업데이트한다.
# - 자기 자신만으로도 이전 합들보다 크다면 이전 합들은 의미가 없어짐을 얘기
curr_sum = max(nums[i], curr_sum + nums[i])

# 현재까지의 합과 이전 max 합을 비교하여 업데이트
max_sum = max(max_sum, curr_sum)

return max_sum
24 changes: 24 additions & 0 deletions number-of-1-bits/liza0525.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,27 @@ def hammingWeight(self, n: int) -> int:
n = n // 2

return bits_sum


# 7기 풀이
# 시간 복잡도: O(log n)
# - 2로 계속 나누고, 이는 2진수 자릿수 만큼 반복
# 공간 복잡도: O(1)
# - 고정된 변수(quotient, remainder)만 사용
class Solution:
def hammingWeight(self, n: int) -> int:
# 10진수를 2진수로 변환하는 과정은 2로 계속 나누면서 그 나머지 값들을 순차적으로 나열하는 것이다.
# 이 때 문자열로 만들지 않고 바로 result에 더해가면 답이 될 수 있음
result = 0

while n > 0:
# 몫과 나머지 계산
quotient, remainder = n // 2, n % 2

# 나머지는 result에 더함
result += remainder

# 몫은 다음 피제수로 사용
n = quotient

return result
30 changes: 30 additions & 0 deletions valid-palindrome/liza0525.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,33 @@ def isPalindrome(self, s: str) -> bool:
return False

return True


# 7기 풀이
# 시간 복잡도: O(n)
# - 문자열 s의 전체 문자를 순회할 때 길이 n만큼의 시간 소요
# 공간 복잡도: O(1)
# - start, end 등의 변수만 사용

class Solution:
def isPalindrome(self, s: str) -> bool:
# two pointer로 각 문자열을 비교하며 palindrome인지 체크한다.
# 해당 문제의 조건 중 하나가 alphanumeric한 문자만 체크하는 것
start, end = 0, len(s) - 1

# 양 끝의 포인터 인덱스가 같아지기 전까지 루프를 돌린다.
while start < end:
if not s[start].isalnum():
# s[start] 문자가 alphanumeric하지 않은 경우엔 start 포인터를 오른쪽으로 한 칸 이동
start += 1
continue
if not s[end].isalnum():
# s[end] 문자가 alphanumeric하지 않은 경우엔 end 포인터를 왼쪽으로 한 칸 이동
end -= 1
continue
if s[start].lower() != s[end].lower():
# 두 문자의 lowercase가 동일하지 않은 경우에는 palindrome이 아니므로 False로 early return 해준다.
return False
start, end = start + 1, end - 1
# while 루프가 다 돌았다면 조건에 걸리지 않고 palindrome임을 충족하므로 True를 return
return True
Loading