[daehyun99] WEEK 01 Solutions#2644
Conversation
📊 daehyun99 님의 학습 현황이번 주 제출 문제
누적 학습 요약
문제 풀이 현황
🤖 이 댓글은 GitHub App을 통해 자동으로 작성되었습니다. 🔢 API 사용량 (gpt-4.1-nano)
|
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
- 패턴: Hash Map / Hash Set
- 설명: 이 코드는 중복 검사를 위해 해시셋을 이용하여 이미 본 숫자를 저장하고, 존재 여부를 빠르게 확인하는 방식으로 구현되어 있습니다.
📊 시간/공간 복잡도 분석
| 복잡도 | |
|---|---|
| Time | O(n) |
| Space | O(n) |
피드백: 집합 자료구조를 사용하여 원소 존재 여부를 빠르게 확인하였으며, 전체 리스트를 한 번 순회하므로 시간 복잡도는 선형이다. 집합이 추가로 사용하는 공간도 원소 수에 비례한다.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
- 패턴: Dynamic Programming
- 설명: 이 코드는 이전 상태의 최적 해를 기반으로 현재 값을 계산하는 방식으로, 최적 부분 구조를 이용하는 동적 프로그래밍 패턴에 속합니다.
📊 시간/공간 복잡도 분석
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(N) | O(n) | ✅ |
| Space | O(N) | O(n) | ✅ |
피드백: 한 번의 리스트 순회로 DP 값을 계산하며, DP 배열 크기만큼 공간을 사용한다. 각 단계에서 이전 두 값만 필요하므로 공간 최적화 가능하다.
개선 제안: 현재 구현이 적절해 보입니다.
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
- 패턴: Hash Map / Hash Set, Union Find
- 설명: 이 코드는 집합을 이용해 연속된 수를 찾으며, 중복 제거와 빠른 탐색을 위해 Hash Set을 활용합니다. Union Find 구조는 사용되지 않지만, 연속된 그룹을 찾는 데 유용하므로 포함시켰습니다.
📊 시간/공간 복잡도 분석
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(N) | O(n) | ✅ |
| Space | O(N) | O(n) | ✅ |
피드백: 집합을 이용해 원소 존재 여부를 빠르게 검사하며, 각 원소는 최대 한 번씩만 검사 및 제거되어 전체 시간 복잡도는 선형이다.
개선 제안: 현재 구현이 적절해 보입니다.
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
- 패턴: Hash Map / Hash Set
- 설명: 코드에서는 defaultdict를 이용해 각 숫자의 빈도수를 저장하는 해시 맵 구조를 사용하여, 빈도수 기반의 연산을 수행합니다.
📊 시간/공간 복잡도 분석
| 복잡도 | |
|---|---|
| Time | O(k * n) |
| Space | O(n) |
피드백: 빈도수 딕셔너리와 결과 리스트를 사용하며, 최대값 찾기 위해 반복문을 k번 수행한다. 이 방법은 비효율적이지만 간단하다.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
- 패턴: Hash Map / Hash Set
- 설명: 코드에서는 set을 이용하여 값의 존재 여부를 빠르게 확인하는 해시 자료구조를 활용하여 Two Sum 문제를 해결합니다. 이 패턴은 빠른 검색이 필요한 경우 자주 사용됩니다.
📊 시간/공간 복잡도 분석
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(n) | O(n) | ✅ |
| Space | O(2n) | O(n) | ❌ |
피드백: 첫 번째 방법은 집합을 이용해 원소 존재 여부를 검사하며, 전체 리스트를 한 번 순회한다. 두 번째 방법은 이중 반복문으로, 시간 복잡도는 제곱에 가깝다.
개선 제안: 집합을 이용한 방법이 더 효율적이므로, 그 방법을 추천한다.
| class Solution: | ||
| def rob(self, nums: List[int]) -> int: | ||
| if len(nums) == 1: | ||
| return nums[0] | ||
|
|
||
| len_nums = len(nums) | ||
| cum_sum = [0 for i in range(len(nums))] | ||
|
|
||
| for i in range(len(nums)): | ||
| if i - 3 >= 0: | ||
| val1 = cum_sum[i-2] + nums[i] | ||
| val2 = cum_sum[i-3] + nums[i] | ||
| cum_sum[i] = max(val1, val2) | ||
| elif i - 2 >= 0: | ||
| cum_sum[i] = cum_sum[i-2] + nums[i] | ||
| else: | ||
| cum_sum[i] = nums[i] | ||
| return max(cum_sum) |
There was a problem hiding this comment.
@daehyun99 제가 리뷰 담당한 PR은 아니지만, 지나가다가 코멘트 한번 남겨봅니다 :)
이 풀이는 bottom up dp를 iterative하게 풀어주신 것 같아서 저도 다음번엔 콜스택 메모리 부담이 있는 재귀방식 대신 요 방식으로 풀어보고 싶네요. 잘 보고갑니다 🙏
| def longestConsecutive(self, nums: List[int]) -> int: | ||
| set_nums = set(nums) | ||
| longest = 0 | ||
|
|
||
| while len(set_nums) > 0 : | ||
| origin_val = set_nums.pop() | ||
| local_len = 1 | ||
|
|
||
| val = origin_val - 1 | ||
| while val in set_nums: | ||
| local_len += 1 | ||
| set_nums.remove(val) | ||
| val -= 1 | ||
|
|
||
| val = origin_val + 1 | ||
| while val in set_nums: | ||
| local_len += 1 | ||
| set_nums.remove(val) | ||
| val += 1 | ||
| longest = max(longest, local_len) |
There was a problem hiding this comment.
@daehyun99 오.. 이 풀이도 생각해보지 못한 방법인데, 오히려 제가 푼 것 보다 더 좋은 것 같습니다. val을 왼쪽과 오른쪽으로 각 방향으로 진행시키면서 구하는 방식이라 중복 체크 될 여지도 없어서 깔끔해 보이네요. 이 방식은 어떻게 떠올리셨는지 궁금합니다.
There was a problem hiding this comment.
@dolphinflow86 안녕하세요! 리뷰해주셔서 감사합니다ㅎㅎ
이전에 비슷한 문제를 Neetcode에서 푼 다음에, 해설 영상을 봤었는데 해설에서 이런 방식으로 풀더라고요.
그거 보고 벽을 느껴서... 이 풀이 방법이 자연스럽게 떠올랐습니다!
JAEKWANG97
left a comment
There was a problem hiding this comment.
안녕하세요! 이번 주 코드 리뷰를 맡은 유재광입니다 ㅎㅎ
전체적으로 풀이가 직관적이라 따라가기 좋았습니다. 보면서 궁금했던 부분과 시간복잡도 측면에서 생각해볼 만한 부분에 코멘트 남겼습니다.
수고하셨습니다!
| for j in range(len(nums)-1, -1, -1): | ||
| val = target - nums[j] | ||
| if val in set_nums: | ||
| i = nums.index(val) |
There was a problem hiding this comment.
이 풀이 흐름 자체는 이해하기 쉬웠습니다!
여기서 nums.index(val)은 리스트를 한 번 더 탐색하다 보니, 주석처럼 완전한 O(n)으로 보기는 조금 어려울 수도 있을 것 같아요. 값이랑 인덱스를 같이 dict에 저장하면 이 부분도 상수 시간에 처리할 수 있을 것 같습니다.
예를 들면 이런 식으로도 풀 수 있을 것 같아요.
seen = {}
for i, num in enumerate(nums):
target_num = target - num
if target_num in seen:
return [seen[target_num], i]
seen[num] = iThere was a problem hiding this comment.
@JAEKWANG97 안녕하세요! 리뷰해주셔서 감사해요!
dict으로 처리하는 방법은 생각 못했었는데, 좋은 것 같군요ㅎㅎ
| nums_dict[num] += 1 | ||
|
|
||
| result = [] | ||
| for i in range(k): |
There was a problem hiding this comment.
빈도수를 먼저 세고, 큰 값부터 하나씩 뽑는 방식이라 흐름이 직관적으로 잘 읽혔습니다.
현재는 k번 반복하면서 매번 전체 딕셔너리를 다시 훑고 있어서, k가 커질수록 비용이 커질 것 같아요. heapq로 크기 k짜리 heap만 유지하면 반복 탐색을 줄일 수 있을 것 같습니다.
There was a problem hiding this comment.
오호.. heapq는 생각 못했었는데 좋은 것 같습니다. 감사합니다ㅎㅎ
답안 제출 문제
작성자 체크 리스트
In Review로 설정해주세요.검토자 체크 리스트
Important
본인 답안 제출 뿐만 아니라 다른 분 PR 하나 이상을 반드시 검토를 해주셔야 합니다!