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
32 changes: 32 additions & 0 deletions binary-tree-maximum-path-sum/dolphinflow86.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/dolphinflow86.py
# N is the number of nodes, and H is the height of the binary tree.
# TC: O(N) - visits each node once in post-order DFS
# SC: O(H) - recursion call stack proportional to tree height (O(N) in worst case)

# 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) -> int:
        max_sum = float("-inf")

        def max_gain(node) -> int:
            nonlocal max_sum
            if not node:
                return 0

            left_gain = max(0, max_gain(node.left))
            right_gain = max(0, max_gain(node.right))

            current_path = node.val + left_gain + right_gain
            max_sum = max(max_sum, current_path)

            return node.val + max(left_gain, right_gain)

        max_gain(root)
        return max_sum
  • 패턴: Depth-First Search, Dynamic Programming
  • 설명: 트리의 각 노드를 후위 순회하며 왼쪽/오른쪽 서브트리의 최대 기여도(0 이상)만 이용해 현재 노드를 경유하는 경로의 합을 계산하고, 이를 전역 최댓값으로 갱신한다. 재귀를 이용한 DFS와 부분해를 합쳐 최댓 경로 합을 구하는 DP 패턴이다.

📊 시간/공간 복잡도 분석

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

피드백: 각 노드에서 좌우 자식의 기여분을 0 이상으로 잘라내고, 현재 노드를 포함한 경로의 합과 전체 최대를 업데이트합니다.

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# N is the number of nodes, and H is the height of the binary tree.
# TC: O(N) - visits each node once in post-order DFS
# SC: O(H) - recursion call stack proportional to tree height (O(N) in worst case)

# 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) -> int:
max_sum = float("-inf")

def max_gain(node) -> int:
nonlocal max_sum
if not node:
return 0

left_gain = max(0, max_gain(node.left))
right_gain = max(0, max_gain(node.right))

current_path = node.val + left_gain + right_gain
max_sum = max(max_sum, current_path)

return node.val + max(left_gain, right_gain)

max_gain(root)
return max_sum
27 changes: 27 additions & 0 deletions graph-valid-tree/dolphinflow86.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.

🏷️ 알고리즘 패턴 분석

graph-valid-tree/dolphinflow86.py
# V is the number of nodes (n), and E is the number of edges.
# TC: O(V + E) - builds adjacency list and traverses graph with BFS
# SC: O(V + E) - stores graph adjacency list and queue/visited set
from collections import deque


class Solution:

    def validTree(self, n: int, edges: list[list[int]]) -> bool:
        if len(edges) != n - 1:
            return False

        adj = [[] for _ in range(n)]
        for u, v in edges:
            adj[u].append(v)
            adj[v].append(u)

        visited = set([0])
        queue = deque([0])

        while queue:
            node = queue.popleft()
            for neighbor in adj[node]:
                if neighbor not in visited:
                    visited.add(neighbor)
                    queue.append(neighbor)

        return len(visited) == n
  • 패턴: Breadth-First Search, Graph
  • 설명: 정점 간의 인접 리스트를 이용해 BFS로 모든 정점을 방문하며 연결 여부를 확인한다. 간선 수를 먼저 체크하고, 시작 정점에서 차례로 방문하여 트리 조건(모든 노드 연결, 사이클 없음)을 만족하는지 검사한다.

📊 시간/공간 복잡도 분석

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

피드백: 간선 개수 조건으로 빠르게 실패를 잡고, 인접 리스트를 이용한 BFS로 모든 정점이 방문되는지 확인합니다.

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

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

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.

🏷️ 알고리즘 패턴 분석

graph-valid-tree/dolphinflow86.py
# V is the number of nodes (n), and E is the number of edges.
# TC: O(V + E) - builds adjacency list and traverses graph with DFS
# SC: O(V + E) - stores graph adjacency list and stack/visited set


class Solution:

    def validTree(self, n: int, edges: list[list[int]]) -> bool:
        if len(edges) != n - 1:
            return False

        adj = [[] for _ in range(n)]
        for u, v in edges:
            adj[u].append(v)
            adj[v].append(u)

        visited = set([0])
        stack = [0]

        while stack:
            node = stack.pop()
            for neighbor in adj[node]:
                if neighbor not in visited:
                    visited.add(neighbor)
                    stack.append(neighbor)

        return len(visited) == n
  • 패턴: Depth-First Search, Graph Traversal, Greedy
  • 설명: 코드가 간선 수가 n-1인지 간단히 확인한 뒤, DFS로 그래프를 탐색하여 모든 노드에 도달하는지 확인합니다. 그래프 탐색의 대표적 패턴인 DFS를 활용하며, 간선-노드 조건으로 트리 여부를 판단합니다.

📊 시간/공간 복잡도 분석

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

피드백: 간선이 n-1개이고 모두 연결되면 트리임을 보장하지만, DFS 탐색으로 모든 정점을 방문하는지 확인한다.

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# V is the number of nodes (n), and E is the number of edges.
# TC: O(V + E) - builds adjacency list and traverses graph with DFS
# SC: O(V + E) - stores graph adjacency list and stack/visited set


class Solution:

def validTree(self, n: int, edges: list[list[int]]) -> bool:
if len(edges) != n - 1:
return False

adj = [[] for _ in range(n)]
for u, v in edges:
adj[u].append(v)
adj[v].append(u)

visited = set([0])
stack = [0]

while stack:
node = stack.pop()
for neighbor in adj[node]:
if neighbor not in visited:
visited.add(neighbor)
stack.append(neighbor)

return len(visited) == n
18 changes: 18 additions & 0 deletions merge-intervals/dolphinflow86.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/dolphinflow86.py
# N is the number of intervals.
# TC: O(N log N) - sorts intervals by start time and merges in a single pass
# SC: O(N) - space for the output array and sorting


class Solution:

    def merge(self, intervals: list[list[int]]) -> list[list[int]]:
        if not intervals:
            return []

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

        for interval in intervals[1:]:
            if interval[0] <= merged[-1][1]:
                merged[-1][1] = max(merged[-1][1], interval[1])
            else:
                merged.append(interval)

        return merged
  • 패턴: Two Pointers, Greedy, Sort
  • 설명: 주어진 코드에서 시작 시간으로 정렬 후 겹치는 구간을 하나의 구간으로 합치는 방식으로 진행되므로 두 포인터로 경계 값을 비교하며(실제 구현은 단일 패스에 가까움) 효율적으로 구간을 병합하는 Greedy 패턴에 해당합니다. 또한 정렬은 문제의 최적 솔루션에 중요한 역할을 합니다.

📊 시간/공간 복잡도 분석

복잡도
Time O(n log 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.

깔끔하게 잘 해결하셨네요!
다만 sort에 key는 적용하실 필요가 있으실지 한번 생각해 보시는것도 좋을것 같아요!

@dolphinflow86 dolphinflow86 Sep 5, 2026

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.

오 넵 짚어주셔서 감사합니다! 그냥 sort만 해도 되겠네요!
반영했습니다.

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/dolphinflow86.py
# N is the number of intervals.
# TC: O(N log N) - sorts intervals by start time and merges in a single pass
# SC: O(N) - space for the output array and sorting


class Solution:

    def merge(self, intervals: list[list[int]]) -> list[list[int]]:
        intervals.sort()
        merged = [intervals[0]]

        for interval in intervals[1:]:
            if interval[0] <= merged[-1][1]:
                merged[-1][1] = max(merged[-1][1], interval[1])
            else:
                merged.append(interval)

        return merged
  • 패턴: Greedy, Two Pointers, Sorting
  • 설명: 간격 배열을 시작점 기준으로 정렬한 뒤, 겹치는 구간을 하나의 구간으로 확장해 합치는 방식으로 최적 해를 구한다. 간단한 탐색으로 이번 구간과 이전 구간의 관계를 판단하며 필요 시 포인터를 이동한다.

📊 시간/공간 복잡도 분석

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

피드백: 입력 간격들을 시작점 기준으로 정렬한 뒤, 현재 구간과 마지막 병합 구간의 끝점을 비교해 필요시 확장한다.

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# N is the number of intervals.
# TC: O(N log N) - sorts intervals by start time and merges in a single pass
# SC: O(N) - space for the output array and sorting


class Solution:

def merge(self, intervals: list[list[int]]) -> list[list[int]]:
intervals.sort()
merged = [intervals[0]]

for interval in intervals[1:]:
if interval[0] <= merged[-1][1]:
merged[-1][1] = max(merged[-1][1], interval[1])
else:
merged.append(interval)

return merged
15 changes: 15 additions & 0 deletions missing-number/dolphinflow86.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/dolphinflow86.py
# N is the length of array nums.
# TC: O(N) - stores elements in a hash set and performs O(1) lookups
# SC: O(N) - uses a hash set of size N


class Solution:

    def missingNumber(self, nums: list[int]) -> int:
        num_set = set(nums)

        for i in range(len(nums) + 1):
            if i not in num_set:
                return i

        return -1
  • 패턴: Hash Map / Hash Set, Greedy
  • 설명: 집합에 원소를 저장한 후, 범위 내에서 누락된 값을 선형 탐색하는 방식으로 해결하므로 해시 집합 패턴이 주로 사용되고, 보조적으로 누락 여부를 빠르게 확인하는 탐색이 포함됩니다.

📊 시간/공간 복잡도 분석

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

피드백: nums의 원소를 집합으로 구성한 뒤 0..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.

해당문제는 사실상 본체가 공간복잡도 O(1)에 해결하는거라 한번 해보시죠!

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.

감사합니다. 한번 시도 해 보겠습니다!

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# N is the length of array nums.
# TC: O(N) - stores elements in a hash set and performs O(1) lookups
# SC: O(N) - uses a hash set of size N


class Solution:

def missingNumber(self, nums: list[int]) -> int:
num_set = set(nums)

for i in range(len(nums) + 1):
if i not in num_set:
return i

return -1
45 changes: 45 additions & 0 deletions reorder-list/dolphinflow86.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/dolphinflow86.py
# N is the number of nodes in the linked list.
# TC: O(N) - finds middle, reverses second half, and merges in linear time
# SC: O(1) - modifies links in place using constant extra pointers

# 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) -> None:
        """
        Do not return anything, modify head in-place instead.
        """
        if not head or not head.next or not head.next.next:
            return

        # 1. Find the middle of the linked list
        slow, fast = head, head
        while fast.next and fast.next.next:
            slow = slow.next
            fast = fast.next.next

        # 2. Reverse the second half of the list
        prev = None
        curr = slow.next
        slow.next = None

        while curr:
            next_node = curr.next
            curr.next = prev
            prev = curr
            curr = next_node

        # 3. Merge two halves (head and prev)
        first, second = head, prev
        while second:
            tmp1, tmp2 = first.next, second.next
            first.next = second
            second.next = tmp1
            first = tmp1
            second = tmp2
  • 패턴: Two Pointers, Linked List
  • 설명: 리스트를 반으로 나누고, 뒤쪽을 역순으로 뒤집은 뒤 두 부분을 교대로 연결하는 방식으로 순서를 재배치한다. 이는 빠른 포인터/느린 포인터로 중간 찾기, 역순 재정렬, 그리고 병합의 3단계로 구성된다.

📊 시간/공간 복잡도 분석

복잡도
Time O(n)
Space 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.

깔끔한 풀이시네여!

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# N is the number of nodes in the linked list.
# TC: O(N) - finds middle, reverses second half, and merges in linear time
# SC: O(1) - modifies links in place using constant extra pointers

# 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) -> None:
"""
Do not return anything, modify head in-place instead.
"""
if not head or not head.next or not head.next.next:
return

# 1. Find the middle of the linked list
slow, fast = head, head
while fast.next and fast.next.next:
slow = slow.next
fast = fast.next.next

# 2. Reverse the second half of the list
prev = None
curr = slow.next
slow.next = None

while curr:
next_node = curr.next
curr.next = prev
prev = curr
curr = next_node

# 3. Merge two halves (head and prev)
first, second = head, prev
while second:
tmp1, tmp2 = first.next, second.next
first.next = second
second.next = tmp1
first = tmp1
second = tmp2
Loading