[daehyun99] WEEK 09 Solutions - #2831
Conversation
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
linked-list-cycle/daehyun99.py
# Time: O(N)
# Space: O(N)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
seen = set()
curr = head
while curr is not None:
if curr.next in seen:
return True
seen.add(curr.next)
curr = curr.next
return False- 패턴: Hash Map / Hash Set, Two Pointers
- 설명: head를 순회하면서 각 노드를 집합에 저장해 이미 본 노드인지 확인하는 해시 세트 기반 탐색 패턴이 사용됩니다. 반복문으로 순회하지만 실제 탐색은 해시 집합으로 중복 여부를 검사합니다.
📊 시간/공간 복잡도 분석
| 복잡도 | |
|---|---|
| Time | O(n) |
| Space | O(n) |
피드백: 해시셋에 노드를 저장해 순회 시 중복 방문 여부를 확인하는 방식으로 동작한다.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
📊 daehyun99 님의 학습 현황이번 주 제출 문제
누적 학습 요약
문제 풀이 현황
🤖 이 댓글은 GitHub App을 통해 자동으로 작성되었습니다. 🔢 API 사용량 (gpt-5-nano)
|
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
maximum-product-subarray/daehyun99.py
# Time: O(N)
# Space: O(N)
class Solution:
def maxProduct(self, nums: List[int]) -> int:
zero_idx = set([i for i in range(len(nums)) if nums[i] == 0])
prefix = [0 for _ in range(len(nums))]
suffix = [0 for _ in range(len(nums))]
val = 1
for i in range(len(nums)):
if i in zero_idx:
val = 1
continue
else:
val *= nums[i]
prefix[i] = val
val = 1
for i in range(len(nums)-1, -1, -1):
if i in zero_idx:
val = 1
continue
else:
val *= nums[i]
suffix[i] = val
return max(max(prefix), max(suffix))- 패턴: Prefix / Suffix Product (using prefix and suffix arrays)
- 설명: 연속 구간의 곱을 0을 기준으로 나눠 왼쪽과 오른쪽에서 누적 곱을 계산하는 패턴으로, 두 포인터나 슬라이딩 윈도우 대신 prefix/suffix 누적으로 최대 곱을 구하는 기법입니다.
📊 시간/공간 복잡도 분석
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(N) | O(n) | ✅ |
| Space | O(N) | O(n) | ✅ |
피드백: 0을 구분자로 삼아 프리픽스와 서픽스를 계산하고 최댓값을 비교한다.
개선 제안: 현재 구현이 적절해 보입니다.
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
minimum-window-substring/daehyun99.py
from collections import Counter
class Solution:
def minWindow(self, s: str, t: str) -> str:
check = Counter(t)
for i, c in enumerate(s):
if c in check:
check[c] -= 1
for key, val in check.items():
if val > 0:
return ""
else:
for i in range(len(s)):
c = s[i]
if c in check:
if check[c] == 0:
left = i
break
check[c] += 1
right = len(s)-1
result = s[left:right+1]
while left < right and 0 <= left:
if s[right] in check:
check[s[right]] += 1
if check[s[right]] <= 0:
if left < right and len(result) > right - left:
result = s[left:right]
right -= 1
else:
while check[s[right]] > 0:
left -= 1
if s[left] in check:
check[s[left]] -= 1
if left < right and len(result) > right - left:
result = s[left:right]
right -= 1
else:
if len(result) > right - left:
result = s[left:right]
right -= 1
return result- 패턴: Two Pointers, Sliding Window, Hash Map / Hash Set
- 설명: 최소 윈도우 부분 문자열 탐색으로, 부분 문자열의 양쪽 포인터를 조정하면서 윈도우를 확장/축소하는 과정이 핵심이다. 해시 맵(Counter)으로 필요한 문자 개수를 추적하고, 슬라이딩 윈도우의 좌우 경계를 이동하며 조건을 만족하는 최솟값을 찾는다.
📊 시간/공간 복잡도 분석
| 복잡도 | |
|---|---|
| Time | O(n * k) |
| Space | O(k) |
피드백: Counter를 이용해 문자 빈도를 관리하지만 전체 알고리즘 흐름이 최적의 투 포인터 방식과 다소 다를 수 있다.
개선 제안: 현재 구현이 충분히 작동하나, 표준 슬라이딩 윈도우 방식으로 개선하면 시간 복잡도가 더 명확해진다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
pacific-atlantic-water-flow/daehyun99.py
# Time: O(m*n)
# Space: O(m*n)
class Solution:
def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]:
def check(matrix, matrix_seen):
while len(matrix) > 0:
m,n = matrix.pop()
if m+1 < len(heights) and heights[m][n] <= heights[m+1][n] and (m+1,n) not in matrix_seen:
matrix.add((m+1,n))
matrix_seen.add((m+1,n))
if m-1 >= 0 and heights[m][n] <= heights[m-1][n] and (m-1,n) not in matrix_seen:
matrix.add((m-1,n))
matrix_seen.add((m-1,n))
if n+1 < len(heights[0]) and heights[m][n] <= heights[m][n+1] and (m,n+1) not in matrix_seen:
matrix.add((m,n+1))
matrix_seen.add((m,n+1))
if n-1 >= 0 and heights[m][n] <= heights[m][n-1] and (m,n-1) not in matrix_seen:
matrix.add((m,n-1))
matrix_seen.add((m,n-1))
return matrix_seen
pacific = set()
pacific_seen = set()
for i in range(len(heights[0])):
pacific.add((0, i))
pacific_seen.add((0, i))
for i in range(1, len(heights)):
pacific.add((i, 0))
pacific_seen.add((i, 0))
p_seen = check(pacific, pacific_seen)
atlantic = set()
atlantic_seen = set()
for i in range(len(heights[0])):
atlantic.add((len(heights)-1, i))
atlantic_seen.add((len(heights)-1, i))
for i in range(0, len(heights)):
atlantic.add((i, len(heights[0])-1))
atlantic_seen.add((i, len(heights[0])-1))
a_seen = check(atlantic, atlantic_seen)
result = []
for p in p_seen:
if p in a_seen:
result.append(list(p))
return result
- 패턴: BFS, Hash Map / Hash Set
- 설명: 두 바다로부터 높이 조건을 만족하는 칸으로 확산시키며 도달 여부를 각각의 BFS로 확인하고, 교차 지점을 찾는 형태로 구현되어 있습니다. 좌표를 큐 대신 스택처럼 다루는 비트 다중 탐색의 구조를 통해 그래프 탐색 패턴이 드러납니다.
📊 시간/공간 복잡도 분석
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(m*n) | O(R*C) | ❌ |
| Space | O(m*n) | O(R*C) | ❌ |
피드백: 두 해수면의 경계에서 출발해 인접한 높이가 같거나 큰 방향으로 확장하는 구현이다.
개선 제안: 현재 구현이 적절해 보입니다.
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
sum-of-two-integers/daehyun99.py
# Time: O(1)
# Space: O(1)
class Solution:
def getSum(self, a: int, b: int) -> int:
mask = 0xFFFFFFFF
max_int = 0x7FFFFFFF
while b != 0 :
carry = (a&b) << 1
a = (a ^ b) & mask
b = carry & mask
return a if a <= max_int else ~(a ^ mask)
"""
# Time: O(N)
# Space: O(N)
class Solution:
def getSum(self, a: int, b: int) -> int:
pos = []
neg = []
for i in [a, b]:
if i < 0 :
for j in range(i, 0):
neg.append(0)
else:
for j in range(i):
pos.append(0)
if len(neg) <= len(pos):
for i in range(len(neg)):
pos.pop()
return len(pos)
else:
for i in range(len(pos)):
neg.pop()
return -1 * len(neg)
"""- 패턴: Bit Manipulation
- 설명: 첫 번째 구현은 비트 연산과 마스킹을 이용해 덧셈의 자리올림을 처리하는 비트 조작 패턴으로 분류됩니다. 두 번째 부분은 비효율적 리스트 조작으로 보이나, 주된 구현은 비트 조작 패턴을 포함합니다.
📊 시간/공간 복잡도 분석
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(1) | O(1) | ✅ |
| Space | O(1) | O(1) | ✅ |
피드백: 첫 번째 구현은 비트 연산을 이용해 음수까지 처리하는 표준 방법이다.
개선 제안: 현재 구현이 적절해 보입니다.
| def check(matrix, matrix_seen): | ||
| while len(matrix) > 0: | ||
| m,n = matrix.pop() | ||
| if m+1 < len(heights) and heights[m][n] <= heights[m+1][n] and (m+1,n) not in matrix_seen: | ||
| matrix.add((m+1,n)) | ||
| matrix_seen.add((m+1,n)) | ||
| if m-1 >= 0 and heights[m][n] <= heights[m-1][n] and (m-1,n) not in matrix_seen: | ||
| matrix.add((m-1,n)) | ||
| matrix_seen.add((m-1,n)) | ||
| if n+1 < len(heights[0]) and heights[m][n] <= heights[m][n+1] and (m,n+1) not in matrix_seen: | ||
| matrix.add((m,n+1)) | ||
| matrix_seen.add((m,n+1)) | ||
| if n-1 >= 0 and heights[m][n] <= heights[m][n-1] and (m,n-1) not in matrix_seen: | ||
| matrix.add((m,n-1)) | ||
| matrix_seen.add((m,n-1)) | ||
| return matrix_seen |
There was a problem hiding this comment.
이 부분이 잘 이해가 안되서 그런데 혹시 어떤 의도로 푸셨는지 설명 해주실 수 있을까요?
There was a problem hiding this comment.
There was a problem hiding this comment.
바다 쪽에서 시작해서 찾는 방식이군요. 상세히 설명 해주셔서 쉽게 이해했습니다. 감사합니다.
| while left < right and 0 <= left: | ||
| if s[right] in check: | ||
| check[s[right]] += 1 | ||
| if check[s[right]] <= 0: | ||
| if left < right and len(result) > right - left: | ||
| result = s[left:right] | ||
| right -= 1 | ||
|
|
||
| else: | ||
| while check[s[right]] > 0: | ||
| left -= 1 | ||
| if s[left] in check: | ||
| check[s[left]] -= 1 | ||
| if left < right and len(result) > right - left: | ||
| result = s[left:right] | ||
| right -= 1 | ||
| else: | ||
| if len(result) > right - left: | ||
| result = s[left:right] | ||
| right -= 1 | ||
| return result |
There was a problem hiding this comment.
혹시 어떤 방식으로 푸신건지 설명 부탁드려도 될까요?
There was a problem hiding this comment.
먼저 check에다가 찾아야하는 각 문자열들의 갯수를 찾고요.
그 후, s에 들어있는 문자열들에 1씩 빼줍니다.(line 6 ~8)
그러면, check 안의 값이 무조건 음수이거나 0이여야 t의 조건을 다 만족하게 됩니다.
이 상황에서 line 13 ~ 19 코드로 t의 조건을 만족하는 s의 끝에서부터 시작하는 left 인덱스 좌표를 찾고, right는 len(s)-1가 됩니다.
그 다음에는 right를 왼쪽으로 옮겨가면서, t 조건을 만족하는지 확인합니다(check 안에 양수가 존재하는지),
예를 들어, 아래의 경우 s[right]가 C일 때, t에는 C가 들어가야해서, right에 -1를 더할 수가 없는데요.
이때, left를 옮겨가면서 s[left]가 C인 경우를 찾습니다.
만약 찾았다면, right를 -1할 수 있습니다.
그 후, 원래의 정답 문자열의 길이와 새로 찾은 s[left:right]의 길이를 비교 후, 길이가 짧은 문자열을 정답으로 반환하게 됩니다.
There was a problem hiding this comment.
설명 해주신 내용이랑 코드 보면서 좀 더 살펴보겠습니다. 감사합니다!

답안 제출 문제
작성자 체크 리스트
In Review로 설정해주세요.검토자 체크 리스트
Important
본인 답안 제출 뿐만 아니라 다른 분 PR 하나 이상을 반드시 검토를 해주셔야 합니다!