[dolphinflow86] WEEK 03 Solutions#2710
Conversation
📊 dolphinflow86 님의 학습 현황이번 주 제출 문제
누적 학습 요약
문제 풀이 현황
🤖 이 댓글은 GitHub App을 통해 자동으로 작성되었습니다. 🔢 API 사용량 (gpt-5-nano)
|
There was a problem hiding this comment.
@DaleStudy/coach 주석에 복잡도 추가 완료
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
- 패턴: Backtracking
- 설명: 코드가 모든 가능한 조합을 탐색하는 재귀 백트래킹으로 목표 합에 맞는 조합을 찾습니다. 가지치기 조건(remain < 후보값)으로 탐색 공간을 줄입니다.
📊 시간/공간 복잡도 분석
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(N^(T/M)) | O(k * C(n, k)) | ❌ |
| Space | O(T/M) | O(k) | ❌ |
피드백: 정렬된 후보를 이용해 남은 합이 현재 값보다 작아지면 가지치기를 수행한다. 재귀 경로의 길이를 저장하는 path와 답을 저장하는 answer의 공간이 주된 추가 공간이다.
개선 제안: 현재 구현이 적절해 보입니다.
There was a problem hiding this comment.
@dolphinflow86 이 문제 시간 복잡도 계산이 까다로운 것 같은데 한번만 풀어서 설명해주실 수 있나요? 이해를 도와주시면 감사하겠습니다 ㅎㅎ
There was a problem hiding this comment.
@okyungjin 맞아요, 복잡도 분석이 까다로웠는데, 기본적으로 모든 조합을 탐색하면 보통 O(2^N)이잖아요? 그런데 이 문제의 경우 같은 숫자를 무제한으로 넣을 수 있기 때문에, 조금 까다로워집니다. 그래서 target 숫자에 도달할때까지 숫자를 계속 선택해서 내려가야하는데, 가장 깊게 내려가는 최악의 경우를 생각 해 보면, 배열에서 가장 작은 숫자(M)만 계속 골라서 target(T) 숫자를 만드는 경우입니다. 따라서 이 경우 트리의 최대 깊이가 T/M이 되고, 우리는 매 노드에서 다음 자식노드로 나갈 수 있는 선택지인 최대 N개를 가지므로, 최종 시간복잡도가 N^(T/M)이 됩니다. 저도 이거 문제 풀면서 분석하면서 이해하게 되었습니다.
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
- 패턴: Dynamic Programming, Memoization, Top-down DP (Recursion + Memoization)
- 설명: 주어진 코드는 문자로 표현된 숫자 원소를 해독하는 경우의 수를 재귀적으로 계산하고, 중복 부분 문제를 메모이제이션으로 해결하는 Top-down DP 패턴을 사용합니다. 1자리/2자리 수를 분리하여 경우의 수를 합산하는 구성으로 DP의 기본 아이디어를 보여줍니다.
📊 시간/공간 복잡도 분석
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(N) | O(n) | ✅ |
| Space | O(N) | O(n) | ✅ |
피드백: idx 위치에서의 중복 부분 문제를 메모이제이션으로 저장해 계산 중복을 제거한다.
개선 제안: 특정 입력에서 memo 배열 크기 관리나 초기화 방식을 명확히 다듬으면 더 견고해진다.
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
- 패턴: Dynamic Programming, Kadane's Algorithm
- 설명: 배열의 연속 부분합 최댓값 문제로, 현재 위치까지의 최댓값과 전체 최댓값을 갱신하는 방식으로 한 번 순회하여 해결한다. DP의 하위 문제 최적화와 Kadane의 아이디어를 이용한 1차원 최적화 패턴이다.
📊 시간/공간 복잡도 분석
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(N) | O(n) | ✅ |
| Space | O(1) | O(1) | ✅ |
피드백: 연속 부분 배열의 합을 현재 값과 비교해 최댓값을 유지한다. 공간은 상수로 충분하다.
개선 제안: 특별한 개선 필요 없어 보이나, 주석을 더 명확히 하면 가독성이 증가한다.
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
- 패턴: Bit Manipulation, Divide and Conquer
- 설명: 주어진 코드는 이진법으로 자릿수를 확인해 1의 개수를 세는 방법으로, 비트를 다루는 Bit Manipulation 패턴과 수를 반으로 나누며 처리하는 Divide and Conquer 성격이 보인다.
📊 시간/공간 복잡도 분석
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(logN) | O(log n) | ✅ |
| Space | O(1) | O(1) | ✅ |
피드백: 루프는 비트 길이만큼 실행되므로 시간은 로그 스케일이다. 초기값과 루프 조건을 단순화하면 좋다.
개선 제안: n을 비트 잉여 없이 고쳐 계산하는 내장 기법(예: Brian Kernighan's 알고리즘)으로 더 간결하게 만들 수 있다.
There was a problem hiding this comment.
🏷️ 알고리즘 패턴 분석
- 패턴: Two Pointers
- 설명: 두 가지 구현 모두 투 포인터를 활용하여 문자열의 양쪽에서 문자들을 비교합니다. 첫 번째는 빈 문자열 제거 없이 인덱스를 이동하고, 두 번째는 필터링 후 새 문자열을 만들어 양끝 비교를 수행합니다.
📊 시간/공간 복잡도 분석
ℹ️ 이 파일에는 2가지 풀이가 포함되어 있어 각각 분석합니다.
풀이 1: Solution.isPalindrome — Time: ✅ O(N) → O(n) / Space: ✅ O(1) → O(1)
| 유저 분석 | 실제 분석 | 결과 | |
|---|---|---|---|
| Time | O(N) | O(n) | ✅ |
| Space | O(1) | O(1) | ✅ |
피드백: 두 구현 모두 필요 문자를 건너뛰고 비교하는 순서를 잘 다룬다. 공간은 상수다.
개선 제안: 필요 시 필터링 버전을 선택적 사용하도록 구조를 정리하면 코드 중복을 줄일 수 있다.
풀이 2: Solution.isPalindrome_filtered — Time: O(n) / Space: O(n)
| 복잡도 | |
|---|---|
| Time | O(n) |
| Space | O(n) |
피드백: 추가 문자열 공간이 필요하지만 구현이 간결하다.
개선 제안: 공간 복잡도를 줄이려면 인덱스 방식의 양방향 탐색으로 구현하는 것이 좋다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
| class Solution: | ||
| def backtrack(self, candidates: List[int], remain: int, start_index: int, path:List[int], answer: List[List[int]]): | ||
| if remain == 0: | ||
| answer.append(path[:]) |
There was a problem hiding this comment.
저는 path.copy()와 같이 작성했는데 이렇게도 쓸 수 있군요
There was a problem hiding this comment.
@okyungjin 네 이렇게 하는방법도 있더라고요? 근데 path.copy가 더 명시적인 것 같아서 경진님 방법이 더 가독성이 좋을 것 같아요!
| while n >= 2: | ||
| if n % 2 == 1: setbit_count += 1 | ||
| n = n // 2 |
There was a problem hiding this comment.
n & 1이랑 n >> 1 처럼 비트 연산으로만 접근하려 했는데, 결국 2로 나눈 나머지를 확인하고 2로 나누는 과정과 같다는 것을 깨달았습니다...
There was a problem hiding this comment.
@okyungjin 비트연산자가 성능면에서는 더 좋을 것 같아요. 이번에는 숫자로 한번 나눠보는 건 어떨까 해서 한번 해봤는데 나름 재미있더라고요 ㅎㅎ
| if remain < candidates[i]: | ||
| break |
There was a problem hiding this comment.
candidates.sort() 정렬한 다음에 이렇게 멈추도록 하면 최적화가 가능하군요!
풀면서 최적화 가능할 것 같은데 .. 하다가 그냥 넘겼는데 하나 배워갑니다. 감사합니다.
There was a problem hiding this comment.
@okyungjin 아 이 부분은 사실 저도 찾아보면서 최적화로 적용했는데, 중복으로 조합을 만들지 않고 이렇게 early return이 가능하더라고요.
|
@dolphinflow86 풀이 잘 봤습니다! 최적화와 복잡도까지 꼼꼼하게 고민하신 점이 인상적이었어요 👍 이번 주 일정에 포함된 Decode Ways와 Maximum Subarray는 제가 아직 풀지 못해서, 먼저 풀어본 세 문제에만 코멘트를 남겼습니다. 두 문제도 풀이를 완료하면 다시 확인하고 코멘트 남기겠습니다. 이번 주도 고생 많으셨습니다! 다음 주도 파이팅하세요. |
답안 제출 문제
작성자 체크 리스트
In Review로 설정해주세요.검토자 체크 리스트
Important
본인 답안 제출 뿐만 아니라 다른 분 PR 하나 이상을 반드시 검토를 해주셔야 합니다!