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
96 changes: 96 additions & 0 deletions 3sum/wozlsla.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
"""
# Intuition
-

# Approach
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

접근법별로 시간복잡도, 공간복잡도를 상세히 작성해주신 내용이 너무 도움이 되었습니다 👍

Copy link
Contributor Author

@wozlsla wozlsla Aug 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

어딘지 기억은 안나지만, 이런식으로 사고하는 방식을 키워보라는 글을 봤어요..
전 문제 풀이 이전에 접근 방식이나 사고 방식이 아직 너무 어려워서.. 지푸라기라도 잡는 심정으로🥲 조금씩 생각한 것들을 풀어내는 걸 연습해보려고 해보고 있어요 ㅎ

index가 모두 다를것,
합 = 0 -> -a = b+c
중복 X -> set : dic와 다르게 가변객체 삽입 X
Two Pointer -> 정렬된 배열을 활용

# Complexity
- Time complexity
- Brute-force : O(N^3)
- Set : O(N^2) - Time Limit Exceeded (memory??)
- Two Pointer : O(N^2)

- Space complexity
- Brute-force : O(N)
- Set : O(N)
- Two Pointer : O(1)
"""

from typing import List


class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:

triplets = set()
nums.sort() # O(NlogN), return None

for i in range(len(nums) - 2): # O(N)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

제가 파이썬 문법을 잘 몰라서 ^^;;
혹시 이 부분은 인덱스가 0부터 nums의 사이즈 -2 까지의 범위인걸까요?_?
혹시 맞다면 범위를 그렇게 잡은 이유가 있을까요~?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

인덱스의 범위가 0~len(nums)-3 입니다! (파이썬에서 range(a, b)는 b 미포함)
nums = [-4, -1, -1, 0, 1, 2] 일 때 nums[0] 부터 nums[3] 까지(-4~0)가 순회 대상입니다.
i 그리고 low, high 두개의 포인터로 총 3개의 수를 보고있기 때문에 유효 범위를 그렇게 설정했습니다!

low, high = i + 1, len(nums) - 1

while low < high: # O(N)
three_sum = nums[i] + nums[low] + nums[high]

if three_sum < 0:
low += 1
elif three_sum > 0:
high -= 1
else:
triplets.add((nums[i], nums[low], nums[high]))
low, high = low + 1, high - 1

return list(triplets)


""" Set
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:

triplets = set()

for i in range(len(nums) - 2):
seen = set()

for j in range(i + 1, len(nums)):
complement = -(nums[i] + nums[j])

if complement in seen:
triplets.add(tuple(sorted([nums[i], nums[j], complement])))

seen.add(nums[j])

return list(triplets)
"""

""" Brute-force
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:

n = len(nums)
result = []

for i in range(n-2):
for j in range(i+1, n-1):
for k in range(j+1, n):
if i != j and i != k and j != k:

if nums[i] + nums[j] + nums[k] == 0:
li = sorted([nums[i], nums[j], nums[k]])

if li not in result: # O(L)
result.append(li)

return result
"""

nums = [-1, 0, 1, 2, -1, -4]
sol = Solution()

print(sol.threeSum(nums))
# [[-1,-1,2],[-1,0,1]]

# print(len({1, 1, 2})) # 2
104 changes: 104 additions & 0 deletions climbing-stairs/wozlsla.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
"""
# Intuition
계단 정상에 오를 수 있는 방법의 수 - 1,2 - 순열? -> X. 자리수가 일정하지 않음

# Approach
접근 1) 1 or 2 로만 이동 가능

풀이 참고
- 계단을 한 번에 최대 2칸 밖에 올라갈 수 없으므로, 3번째 칸에 발을 딛기 위해서는 바로 아래 칸인 2번째 칸이나 적어도 1번째 칸에 반드시 먼저 올라와있어야 함.
- 즉, n 칸에 발을 딛기위해서는 그 전에 n - 1 칸이나 n - 2 칸까지 올라와왔어야 한다.

접근 2)
4 -> 5
1 1 1 1
2 1 1
1 2 1
1 1 2
2 2

5 -> 8
1 1 1 1 1
2 2 1
1 2 2
2 1 2
1 1 1 2
1 1 2 1
1 2 1 1
2 1 1 1

n=5까지만 봤을 때 늘어나는 규칙이 피보나치수열과 같음. (hint)

# Complexity
- Time complexity
- DP 1 : O(N)
- DP 2 : O(N)

- Recursive 1 : O(2^N)
- Recursive 2 (caching): O(N)

- Space complexity
- DP 1 : O(N)
- DP 2 : O(1)

- Recursive 1 : O(N)
- Recursive 2 (caching): O(N)

"""


# DP 2 (공간 최적화)
class Solution:
def climbStairs(self, n: int) -> int:

if n < 3:
return n

pre, cur = 1, 2

for _ in range(n - 2):
pre, cur = cur, pre + cur # 순서 !

return cur


""" DP 1
class Solution:
def climbStairs(self, n: int) -> int:

dp = {1:1, 2:2}

for i in range(3, n+1):
dp[i] = dp[i-1] + dp[i-2]

return dp[n]
"""

""" Memoization (재귀 + 캐싱)
class Solution:
def climbStairs(self, n: int) -> int:
memo = {}

def _climb(n):

if n not in memo:
if n < 3:
memo[n] = n
else:
memo[n] = _climb(n - 1) + _climb(n - 2)

return memo[n]

return _climb(n)
"""


""" Recursive
class Solution:
def climbStairs(self, n: int) -> int:

if n < 3:
return n

return self.climbStairs(n-1) + self.climbStairs(n-2)
"""
67 changes: 67 additions & 0 deletions house-robber/wozlsla.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""
# Intuition
<!-- Describe your first thoughts on how to solve this problem. -->
# Approach
<!-- Describe your approach to solving the problem. -->
# Complexity
- Time complexity:
- Space complexity:
"""


# DP
class Solution:
def rob(self, nums: List[int]) -> int:

# initialize dp array
dp = [0] * (len(nums) + 1)

if nums:
dp[1] = nums[0]

for n in range(2, len(dp)):
# current house : nums[n-1]
rob_current = nums[n - 1] + dp[n - 2]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오오.. dp로 풀은게 너무 흥미로워요 👍
그런데 rob_current 이 부분이 사실 조금 이해가 안되서 😅
n 이라는 인덱스가 current 인걸까용? 아님 n-1 이 current 인걸까요..?
그럼 n-1이 current 이라면 dp[n-2]는 current 직전까지의 훔친 값들의 누적일까요..?_?

Copy link
Contributor Author

@wozlsla wozlsla Aug 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nums 와 dp의 인덱스를 다르게 가져가고 있습니다! n은 dp의 인덱스이고, nums[n-1]이 현재 털 집입니다.
nums -> 각 집의 금액, dp -> 털 수 있는 최대 누적 금액 [0(아무 집도 없을 때), ...]
따라서 nums[n-1]이 현재 집입니다. dp[n-2]는 2칸 전 집까지의 최댓값 입니다.

  • n번째 dp는 nums[n-1] (현재 집)을 털지 말지 결정
  • rob_current: 현재 집을 털고, n-2까지의 최댓값 더하기
    인덱스를 이렇게 가져간 이유는 인덱스 문제 처리를 위한 예외를 두지 않고, 식 하나로 해결하기 위해 구현한 방식입니다!

저번주 문제인데 같이 봐주셨네요!! 그때는 DP로 접근하는 방법으로는 스스로 못 풀어서 이번에 해설을 보며 풀이했습니다.
아직 알고리즘 풀이가 익숙하지 않은 단계라서, 질문에 답변하느라 다시 봤는데 풀어놓고도 생소하네요.. 덕분에 재정리할 수 있었습니다. 감사합니다 ☺️

skip_current = dp[n - 1]

dp[n] = max(rob_current, skip_current)

return dp[-1]


""" Recursive + Memoization
class Solution:
def rob(self, nums: List[int]) -> int:
memo = {}
def dfs(start):
if start in memo:
return memo[start]
if start >= len(nums):
memo[start] = 0
else:
memo[start] = max(nums[start] + dfs(start + 2), dfs(start + 1))
return memo[start]
return dfs(0)
"""

""" Recursive
class Solution:
def rob(self, nums: List[int]) -> int:
def dfs(start):
if start >= nums(len):
return 0
return max(nums[start] + dfs[start+2], dfs[start+1])
return dfs(0)
"""
82 changes: 82 additions & 0 deletions product-of-array-except-self/wozlsla.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
"""
# Intuition
하나씩 순회하면서 나머지 값들을 곱함
# Approach
접근 1) 원형 큐를 사용하면?
현재 제외하려는 요소를 popleft()로 제거하고, 나머지 요소들의 곱을 계산한 뒤, 다시 그 요소를 append()하여 다음 반복을 위해 덱의 순서를 회전
접근 2)
1 b c d --> 1 x bcd
a 1 c d --> a x cd
a b 1 d --> ab x d
a b c 1 --> abc x 1
# Complexity
- Time complexity : O(N)
- Space complexity : O(N) / O(1)
"""

from typing import List


class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:

n = len(nums)
res = [1] * n

prefix_product = 1
for i in range(n):
res[i] = prefix_product
prefix_product *= nums[i]

suffix_product = 1
for i in range(n - 1, -1, -1):
res[i] *= suffix_product
suffix_product *= nums[i]


"""
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
# 중복 계산을 피하는 방법?
res_1 = [1] * len(nums)
res_2 = [1] * len(nums)
for n in range(1, len(nums)): # [1, 1(a), 2(ab), 6(abc)]
res_1[n] = res_1[n - 1] * nums[n - 1]
# reverse X -> range를 반대로
for n in range(len(nums) - 1, -1, -1): # [1, 4(d), 12(cd), 24(bcd)]
res_2[n] = res_2[n + 1] * nums[n + 1]
res_2.reverse()
return [res_1[i] * res_2[i] for i in range(len(nums))]
sol = Solution()
print(sol.productExceptSelf([1, 2, 3, 4]))
"""


"""
# deque : O(N^2)
from collections import deque
import math
class Solution:
def productExceptSelf(self, nums: List[int]) -> List[int]:
nums = deque(nums)
result = []
for _ in range(len(nums)): # O(N)
tmp = nums.popleft()
result.append(math.prod(nums)) # O(N)
nums.append(tmp)
return result
"""
Loading