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
30 changes: 30 additions & 0 deletions binary-tree-maximum-path-sum/yuseok89.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.

🏷️ 알고리즘 패턴 분석

binary-tree-maximum-path-sum/yuseok89.py
# TC: O(N)
# SC: O(1)
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def maxPathSum(self, root: Optional[TreeNode]) -> int:

        ans = float('-inf')

        def get_max(cur: Optional[TreeNode]) -> int:
            nonlocal ans

            if cur is None:
                return 0

            left_max = get_max(cur.left)
            right_max = get_max(cur.right)

            ans = max(ans, cur.val, cur.val + left_max, cur.val + right_max, cur.val +left_max + right_max)

            return max(cur.val, cur.val + max(left_max, right_max))

        get_max(root)

        return ans
  • 패턴: Depth-First Search, Dynamic Programming, Binary Search
  • 설명: 트리의 각 노드에서 좌우 자식의 최대 합을 재귀적으로 계산하며, 글로벌 최댓값을 갱신하는 방식은 DFS로 트리를 순회하고, 각 노드의 정보를 재활용해 최댓값을 누적하는 DP적 패턴과 같이 작동합니다. 또한 부분해를 합으로 고려하는 구조는 트리에서의 최적해 구성의 DP 성질을 반영합니다.

📊 시간/공간 복잡도 분석

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

피드백: 각 노드에서 왼쪽/오른쪽 자식에서의 최대 증가분을 구하고, 이를 이용해 현재 노드를 포함한 경로의 최대 합과 리턴 값을 계산한다.

개선 제안: 현재 구현은 전형적인 DFS 방식으로 동작하며, 공간 복잡도는 재귀 호출 깊이에 따라 좌우 깊이의 합 중 최댓값인 h에 비례한다. 필요 시 순회 방식으로의 변환이나 tail recursion 최적화를 고려해도 된다.

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.

🏷️ 알고리즘 패턴 분석

binary-tree-maximum-path-sum/yuseok89.py
# TC: O(N)
# SC: O(H)
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def maxPathSum(self, root: Optional[TreeNode]) -> int:

        ans = float('-inf')

        def get_max(cur: Optional[TreeNode]) -> int:
            nonlocal ans

            if cur is None:
                return 0

            left_max = get_max(cur.left)
            right_max = get_max(cur.right)

            ans = max(ans, cur.val, cur.val + left_max, cur.val + right_max, cur.val +left_max + right_max)

            return max(cur.val, cur.val + max(left_max, right_max))

        get_max(root)

        return ans
  • 패턴: Binary Search, Depth-First Search, Dynamic Programming, Tree Traversal
  • 설명: 주어진 코드는 이진 트리에서 모든 경로의 합을 탐색하며, 자식 노드의 정보를 재귀적으로 합산해 최댓값을 업데이트한다. 각 노드에서 좌우 서브트리 정보를 활용해 최댓 경로를 계산하는 방식은 DFS와 DP의 혼합 패턴으로 볼 수 있다.

📊 시간/공간 복잡도 분석

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

피드백: 전위 탐색과 재귀를 이용해 자식 노드의 최대 증가 합을 합산하고, 현재 노드에서 형성 가능한 최대 경로를 갱신한다.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# TC: O(N)
# SC: O(H)
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def maxPathSum(self, root: Optional[TreeNode]) -> int:

ans = float('-inf')

def get_max(cur: Optional[TreeNode]) -> int:
nonlocal ans

if cur is None:
return 0

left_max = get_max(cur.left)
right_max = get_max(cur.right)

ans = max(ans, cur.val, cur.val + left_max, cur.val + right_max, cur.val +left_max + right_max)

return max(cur.val, cur.val + max(left_max, right_max))

get_max(root)

return ans

25 changes: 25 additions & 0 deletions merge-intervals/yuseok89.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.

🏷️ 알고리즘 패턴 분석

merge-intervals/yuseok89.py
# TC: O(NlogN)
# SC: O(N)
class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:

        ans = list()

        intervals.sort(key=lambda x:x[0])

        ans.append([intervals[0][0]])

        end = intervals[0][1]

        for idx in range(1, len(intervals)):
            if intervals[idx][0] <= end:
                end = max(end, intervals[idx][1])
            else:
                ans[-1].append(end)
                ans.append([intervals[idx][0]])
                end = intervals[idx][1]

        ans[-1].append(end)

        return ans
  • 패턴: Greedy, Sort
  • 설명: Intervals 정렬 후 겹치는 구간을 하나의 구간으로 합치는 과정을 사용하므로 Greedy 패턴으로 분류되며, 먼저 시작점을 기준으로 정렬하는 전략이 핵심입니다. 또한 투포인터처럼 현재 구간의 끝과 다음 구간의 시작을 비교해 확장 여부를 결정합니다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(NlogN) O(n log n)
Space O(N) 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.

구현 상당히 깔끔하게 잘 하셨네요

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# TC: O(NlogN)
# SC: O(N)
class Solution:
def merge(self, intervals: List[List[int]]) -> List[List[int]]:

ans = list()

intervals.sort(key=lambda x:x[0])

ans.append([intervals[0][0]])

end = intervals[0][1]

for idx in range(1, len(intervals)):
if intervals[idx][0] <= end:
end = max(end, intervals[idx][1])
else:
ans[-1].append(end)
ans.append([intervals[idx][0]])
end = intervals[idx][1]

ans[-1].append(end)

return ans

12 changes: 12 additions & 0 deletions missing-number/yuseok89.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.

🏷️ 알고리즘 패턴 분석

missing-number/yuseok89.py
# TC: O(N)
# SC: O(1)
class Solution:
    def missingNumber(self, nums: List[int]) -> int:
        n = len(nums)
        total = n * (n + 1) // 2

        for num in nums:
            total -= num

        return total
  • 패턴: Greedy, Bit Manipulation, Dynamic Programming, Hash Map / Hash Set, Divide and Conquer, Two Pointers, Sliding Window, Backtracking, DFS, BFS, Union Find, Trie, Heap / Priority Queue, Monotonic Stack, Binary Search
  • 설명: 해당 코드는 수의 합 공식을 이용해 누락된 숫자를 구하는 방식으로 전체 합에서 배운 값들을 차감하는 아이디어를 사용한다. 문제의 시간복잡도는 O(N), 공간복잡도는 O(1)로 구현된다.

📊 시간/공간 복잡도 분석

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

피드백: 등차수열의 합 공식을 이용해 한 번의 순회로 누락 숫자를 구한다.

개선 제안: 현재 구현이 간단하고 효율적이다. 입력에 빈 배열 등의 특수 케이스를 가정하지 않는다면 추가 방어가 필요할 수 있다.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# TC: O(N)
# SC: O(1)
class Solution:
def missingNumber(self, nums: List[int]) -> int:
n = len(nums)
total = n * (n + 1) // 2

for num in nums:
total -= num

return total

37 changes: 37 additions & 0 deletions reorder-list/yuseok89.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.

🏷️ 알고리즘 패턴 분석

reorder-list/yuseok89.py
# TC: O(N)
# SC: O(1)
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reorderList(self, head: Optional[ListNode]) -> None:
        """
        Do not return anything, modify head in-place instead.
        """

        if not head or not head.next:
            return

        def rec(right: Optional[ListNode]) -> Optional[ListNode]:
            if not right:
                return head

            left = rec(right.next)

            if not left:
                return None

            if left == right or left.next == right:
                right.next = None
                return None

            nxt_left = left.next
            left.next = right
            right.next = nxt_left

            return nxt_left

        rec(head)
  • 패턴: Recursion, Two Pointers, Linked List
  • 설명: 재귀를 이용해 리스트의 끝에서부터 왼쪽 포인터를 움직이며 노드를 재배치하는 방식으로, 두 포인터가 서로 인접할 때 종료 조건을 걸고 연결을 재구성합니다. 부분적으로 재귀 깊이를 통해 리스트를 반전된 방향으로 순회하며 O(N) 시간, O(1) 추가 공간 특성을 갖습니다.

📊 시간/공간 복잡도 분석

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

피드백: 전형적인 위상 정렬/데이터 구조 조합으로 재배치한다. 재귀와 포인터 조작으로 in-place를 달성한다.

개선 제안: 현재 구현은 재귀를 이용해 오른쪽 부분을 순회하며 재배치를 시도한다. 구현의 복잡도가 다소 높으므로 반복적 접근으로 리팩토링을 고려해볼 수 있다.

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.

🏷️ 알고리즘 패턴 분석

reorder-list/yuseok89.py
# TC: O(N)
# SC: O(N)
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def reorderList(self, head: Optional[ListNode]) -> None:
        """
        Do not return anything, modify head in-place instead.
        """

        if not head or not head.next:
            return

        def rec(right: Optional[ListNode]) -> Optional[ListNode]:
            if not right:
                return head

            left = rec(right.next)

            if not left:
                return None

            if left == right or left.next == right:
                right.next = None
                return None

            nxt_left = left.next
            left.next = right
            right.next = nxt_left

            return nxt_left

        rec(head)
  • 패턴: Two Pointers, Recursion, Linked List
  • 설명: 재귀를 이용해 리스트의 좌측 노드와 우측 노드를 교차로 연결하는 방식으로, 재귀 호출로 좌측 포인터를 얻고 좌우를 번갈아 붙여 리스트를 재배치한다. 연결 순서를 재구성하는 연산은 순차적으로 진행되며, 재귀 깊이와 포인터 조작이 핵심 포인트다.

📊 시간/공간 복잡도 분석

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

피드백: 재귀를 이용해 오른쪽 부분의 노드를 따라가며 왼쪽 부분과 연결을 구성한다. 재귀 깊이가 O(n)까지 증가하므로 공간 복잡도는 스택 깊이에 의해 결정된다.

개선 제안: 고려해볼 만한 대안: 재귀 대신 두 포인터(빠른/느린)로 중간을 분리하고, 뒤에서부터 연결하기보다 배열에 노드를 모아 역순으로 연결하는 방식으로 공간 사용을 줄일 수 있다. 또한 tail 포인터를 유지해 불필요한 노드 재할당 없이 O(1) 공간으로 구현 가능하다.

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# TC: O(N)
# SC: O(N)
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reorderList(self, head: Optional[ListNode]) -> None:
"""
Do not return anything, modify head in-place instead.
"""

if not head or not head.next:
return

def rec(right: Optional[ListNode]) -> Optional[ListNode]:
if not right:
return head

left = rec(right.next)

if not left:
return None

if left == right or left.next == right:
right.next = None
return None

nxt_left = left.next
left.next = right
right.next = nxt_left

return nxt_left

rec(head)

Loading