Skip to content

[alphaorderly] WEEK 12 Solutions - #2854

Merged
alphaorderly merged 1 commit into
DaleStudy:mainfrom
alphaorderly:week-12
Sep 11, 2026
Merged

[alphaorderly] WEEK 12 Solutions#2854
alphaorderly merged 1 commit into
DaleStudy:mainfrom
alphaorderly:week-12

Conversation

@alphaorderly

Copy link
Copy Markdown
Contributor

답안 제출 문제

작성자 체크 리스트

  • Projects의 오른쪽 버튼(▼)을 눌러 확장한 뒤, Week를 현재 주차로 설정해주세요.
  • 문제를 모두 푸시면 프로젝트에서 StatusIn Review로 설정해주세요.
  • 코드 검토자 1분 이상으로부터 승인을 받으셨다면 PR을 병합해주세요.

검토자 체크 리스트

Important

본인 답안 제출 뿐만 아니라 다른 분 PR 하나 이상을 반드시 검토를 해주셔야 합니다!

  • 바로 이전에 올라온 PR에 본인을 코드 리뷰어로 추가해주세요.
  • 본인이 검토해야하는 PR의 답안 코드에 피드백을 주세요.
  • 토요일 전까지 PR을 병합할 수 있도록 승인해주세요.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🏷️ 알고리즘 패턴 분석

non-overlapping-intervals/alphaorderly.py
"""
# 시간 복잡도: O(n log n)
# 공간 복잡도: O(1)
#
# 1. 인터벌을 끝점을 기준으로 오름차순 정렬한다.
# 2. 첫 번째 인터벌의 끝점을 기준으로 순회하면서,
#    다음 인터벌의 시작점이 현재 끝점보다 작으면 겹치는 것으로 간주하여 카운트를 증가시킨다.
#    - 겹치면(count += 1) 끝점은 그대로 둔다.
#    - 겹치지 않으면 끝점을 현재 인터벌의 끝점으로 업데이트한다.
# 3. 마지막에 카운트를 반환한다.
#
# 왜 최선인가?
# - 끝점이 가장 작은 것부터 남겨두면 이후로 더 많은 인터벌을 남길 수 있다.
# - 이는 최대한 많은 인터벌을 남기기 위해 최소 개수의 인터벌만 제거하게 되는 그리디 전략이다.
"""
class Solution:
    def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:
        intervals.sort(key=lambda k: k[1])
        N = len(intervals)

        count = 0
        end = intervals[0][1]

        for i in range(1, N):
            event_start, event_end = intervals[i]

            if event_start < end:
                count += 1
            else:
                end = event_end

        return count
  • 패턴: Greedy
  • 설명: 주요 아이디어가 끝점을 기준으로 정렬한 뒤, 겹치는 경우를 최소 제거로 해결하는 그리디 전략으로 구성되어 있습니다. 먼저 끝점이 작은 인터벌을 남겨두고, 겹치면 제거 카운트를 증가시키며 끝점을 유지하거나 업데이트합니다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(n log n) O(n log n)
Space O(1) O(1)

피드백: 종료점을 오름차순으로 정렬한 뒤 한 번 순회하며 겹치는 경우를 세서 제거 수를 계산한다. 추가 공간은 상수

개선 제안: 현재 구현이 적절해 보입니다.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🏷️ 알고리즘 패턴 분석

number-of-connected-components-in-an-undirected-graph/alphaorderly.py
"""
# 시간 복잡도: O(n) (Union Find 연산은 경로 압축과 rank 활용으로 Amortized O(1))
# 공간 복잡도: O(n)
#
# Union-Find(유니온 파인드, Disjoint Set Union) 알고리즘을 사용해 무방향 그래프의 연결 요소(connected components) 개수를 계산한다.
#
# 알고리즘 단계:
# 1. 각 노드는 자기 자신을 부모로 갖도록(parent 배열) 초기화한다.
# 2. 트리의 깊이(랭크, rank)를 저장하는 배열을 초기화한다.
# 3. 간선을 하나씩 확인하며 union 연산으로 두 노드를 같은 집합으로 합친다.
#    - 이미 같은 집합인 경우엔 아무 작업도 하지 않는다.
#    - 서로 다른 집합을 합치면, 연결 요소 개수를 1 감소시킨다.
# 4. 모든 간선을 처리하고 남은 연결 요소 개수(ans)를 반환한다.
"""
class UnionFind:
    def __init__(self, n: int):
        self.parent = [-1] * n
        self.rank = [0] * n

    def find(self, target: int) -> int:
        if self.parent[target] == -1:
            return target

        self.parent[target] = self.find(self.parent[target])
        return self.parent[target]

    def union(self, a: int, b: int) -> bool:
        a = self.find(a)
        b = self.find(b)

        if a == b:
            return False

        if self.rank[a] < self.rank[b]:
            a, b = b, a

        self.parent[b] = a
        if self.rank[a] == self.rank[b]:
            self.rank[a] += 1

        return True

class Solution:
    def countComponents(self, n: int, edges: List[List[int]]) -> int:
        uf = UnionFind(n)
        ans = n

        for a, b in edges:
            if uf.union(a, b):
                ans -= 1

        return ans
  • 패턴: Union Find
  • 설명: 주어진 코드는 서로의 연결 여부를 관리하는 유니온 파인드(Disjoint Set Union)로 그래프의 연결 요소 개수를 계산한다. 간선을 하나씩 합치며 서로 다른 집합이면 연결 요소를 감소시키는 방식으로 구현된다.

📊 시간/공간 복잡도 분석

복잡도
Time O(n + m α(n))
Space O(n)

피드백: 초기화와 패런트/랭크를 사용해 서로 다른 집합을 합치며 연결 요소 수를 업데이트한다

개선 제안: 현재 구현이 적절해 보입니다.

💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🏷️ 알고리즘 패턴 분석

remove-nth-node-from-end-of-list/alphaorderly.py
"""
# 시간 복잡도: O(n)
# 공간 복잡도: O(1)
#
# 한 번의 순회(one pass)로 연결 리스트의 끝에서 n번째 노드를 제거하는 방법:
# 1. dummy 노드를 만들어 head의 앞에 연결한다.
# 2. forerunner 포인터를 n칸 먼저 이동시킨다.
# 3. forerunner와 lastcomer(초기: dummy)를 같이 한 칸씩 이동하며, forerunner가 끝(None)에 도달하면 lastcomer는 제거할 노드 바로 앞에 위치하게 된다.
# 4. lastcomer.next를 갱신하여 n번째 노드를 제거한다.
"""
class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        dummy = ListNode(0)
        dummy.next = head

        forerunner = head
        lastcomer = dummy

        for _ in range(n):
            forerunner = forerunner.next

        while forerunner:
            forerunner = forerunner.next
            lastcomer = lastcomer.next

        lastcomer.next = lastcomer.next.next

        return dummy.next
  • 패턴: Two Pointers, Linked List
  • 설명: 목적 노드 제거를 위해 두 포인터를 활용하는 대표적인 패턴으로, 하나를 n칸 먼저 움직이고 이후 같이 한 칸씩 이동시키며 타겟 노드를 찾는다. 연결 리스트의 한 번의 순회로 문제를 해결한다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(n) O(n)
Space O(1) O(1)

피드백: 더미 헤드 및 두 포인터를 사용해 제거 위치를 찾아 연결을 끊는다

개선 제안: 현재 구현이 적절해 보입니다.

Comment thread same-tree/alphaorderly.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🏷️ 알고리즘 패턴 분석

same-tree/alphaorderly.py
"""
시간 복잡도 : O(n)
공간 복잡도 : O(n)

재귀적으로 두 이진 트리의 노드를 비교하면서 값이 같은지 확인한다.
"""
class Solution:
    def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
        # 두 노드가 둘다 None 이면 True 를 반환한다.
        if p is q:
            return True

        # 두 노드중 하나가 None 이면 False 를 반환한다.
        if not (p and q):
            return False

        # 둘다 None이 아니라면 값을 비교하고 왼쪽과 오른쪽 서브트리도 재귀적으로 비교한다.
        return (
            p.val == q.val
            and self.isSameTree(p.left, q.left)
            and self.isSameTree(p.right, q.right)
        )
  • 패턴: Binary Search, Depth-First Search, Tre e Pattern
  • 설명: 추가 설명: 이 코드는 두 트리의 모든 노드를 재귀적으로 비교하여 동일 여부를 확인한다. 각 노드에서 좌우 자식으로 DFS 방식으로 순회하며 조건을 검사한다. 트리 구조를 다룬다는 점에서 DFS의 특성을 띈다.

📊 시간/공간 복잡도 분석

복잡도
Time O(n)
Space O(h)

피드백: 두 트리의 동치 여부를 단순 비교하며 좌우 서브트리까지 재귀적으로 확인한다

개선 제안: 현재 구현이 적절해 보입니다.

💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!

@dalestudy

dalestudy Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

📊 alphaorderly 님의 학습 현황

이번 주 제출 문제

문제 난이도 유형 분석
non-overlapping-intervals Medium ✅ 의도한 유형
number-of-connected-components-in-an-undirected-graph Medium ✅ 의도한 유형
remove-nth-node-from-end-of-list Medium ✅ 의도한 유형
same-tree Easy ✅ 의도한 유형
serialize-and-deserialize-binary-tree Hard ✅ 의도한 유형

누적 학습 요약

  • 풀이한 문제: 55 / 75개
  • 이번 주 유형 일치율: 100% (5문제 중 5문제 일치)

문제 풀이 현황

카테고리 진행도 완료
Array ■■■■■■■ 10 / 10 (Medium 7, Easy 3)
Dynamic Programming ■■■■■■□ 10 / 11 (Easy 1, Medium 9)
String ■■■■■■□ 9 / 10 (Medium 5, Hard 1, Easy 3)
Linked List ■■■■■■□ 5 / 6 (Easy 3, Hard 1, Medium 1)
Binary ■■■■■■□ 4 / 5 (Easy 3, Medium 1)
Graph ■■■■■□□ 6 / 8 (Medium 6)
Matrix ■■■■■□□ 3 / 4 (Medium 3)
Heap ■■■■■□□ 2 / 3 (Hard 1, Medium 1)
Tree ■■■□□□□ 6 / 14 (Hard 1, Medium 3, Easy 2)
Interval ■□□□□□□ 1 / 5 (Medium 1)

🤖 이 댓글은 GitHub App을 통해 자동으로 작성되었습니다.

🔢 API 사용량 (gpt-5-nano)
요청 입력 토큰 출력 토큰 합계 비용
1 2,641 204 2,845 $0.000214

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🏷️ 알고리즘 패턴 분석

serialize-and-deserialize-binary-tree/alphaorderly.py
# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

"""
# 시간 복잡도: O(n)
# 공간 복잡도: O(n)
#
# 이 코드는 preorder(전위 순회)를 이용해 이진 트리를 문자열로 직렬화하고,
# 다시 preorder 순서로 문자열을 역직렬화하여 트리를 복원한다.
#
# 1. serialize 함수는 preorder 순회로 트리 노드를 방문하며 값을 문자열로 저장하고,
#    None 자리는 특수문자(*)로 표기한다.
# 2. deserialize 함수는 preorder 순서의 문자열을 한 항목씩 읽어가며
#    *이면 None, 숫자면 그 값의 TreeNode를 재귀적으로 생성한다.
"""
class Codec:

    def serialize(self, root):
        ans = []

        def preorder(node: Optional[TreeNode]):
            if not node:
                ans.append("*")
                return

            ans.append(str(node.val))
            preorder(node.left)
            preorder(node.right)

        preorder(root)
        return ','.join(ans)

    def deserialize(self, data):
        data = iter(data.split(','))

        def preorder() -> TreeNode:
            current = next(data)

            if current == '*':
                return None

            node = TreeNode(int(current))
            node.left = preorder()
            node.right = preorder()

            return node

        return preorder()


# Your Codec object will be instantiated and called as such:
# ser = Codec()
# deser = Codec()
# ans = deser.deserialize(ser.serialize(root))
  • 패턴: Depth-First Search, Binary Search, Divide and Conquer, Hash Map / Hash Set
  • 설명: 전위 순회 기반으로 트리를 방문하며 재귀적으로 노드를 생성/복원하므로 DFS 구성이며, 재귀적 탐색이 핵심이다. 문제 맥락에서 분할된 서브트리 재구성은 Divide and Conquer의 성격도 보인다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(n) O(n)
Space O(n) O(n)

피드백: None 노드도 '*'로 표기하여 구조를 보존한다

개선 제안: 현재 구현이 적절해 보입니다.

@yuseok89
yuseok89 self-requested a review September 8, 2026 14:52

@yuseok89 yuseok89 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

이번 한 주도 고생많으셨습니다.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

deserialize 를 재귀로 구현한 부분이 좋네요 !

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

회원님 코드도 엄청 인상적이였어요! 깔끔하게 잘 하셨더라구요!

@alphaorderly
alphaorderly merged commit b8e1224 into DaleStudy:main Sep 11, 2026
3 checks passed
@github-project-automation github-project-automation Bot moved this from In Review to Completed in 리트코드 스터디 8기 Sep 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Completed

Development

Successfully merging this pull request may close these issues.

2 participants