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 find-median-from-data-stream/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.

🏷️ 알고리즘 패턴 분석

find-median-from-data-stream/dolphinflow86.py
# N is the number of elements added to the data stream.
# TC: O(log N) for addNum, O(1) for findMedian
# SC: O(N) - stores elements split into two heaps

import heapq


class MedianFinder:

    def __init__(self):
        self.small = []  # max-heap (store negative values)
        self.large = []  # min-heap

    def addNum(self, num: int) -> None:
        heapq.heappush(self.small, -num)

        if self.small and self.large and (-self.small[0] > self.large[0]):
            val = -heapq.heappop(self.small)
            heapq.heappush(self.large, val)

        if len(self.small) > len(self.large) + 1:
            val = -heapq.heappop(self.small)
            heapq.heappush(self.large, val)

        if len(self.large) > len(self.small):
            val = heapq.heappop(self.large)
            heapq.heappush(self.small, -val)

    def findMedian(self) -> float:
        if len(self.small) > len(self.large):
            return float(-self.small[0])
        return (-self.small[0] + self.large[0]) / 2.0
  • 패턴: Heap / Priority Queue, Hash Map / Hash Set
  • 설명: 이 문제는 두 개의 힙을 이용해 데이터 스트림에서 중간값을 빠르게 찾는 구조로, 추가 시 힙 간 균형을 맞춰 중앙값을 O(1) 또는 O(log N)으로 반환합니다. 힙을 활용한 데이터 분리와 균형 유지가 핵심 패턴입니다.

📊 시간/공간 복잡도 분석

ℹ️ 이 파일에는 2가지 풀이가 포함되어 있어 각각 분석합니다.

풀이 1: MedianFinder.addNum — Time: O(log n) / Space: O(n)
복잡도
Time O(log n)
Space O(n)

피드백: 두 개의 힙으로 삽입 시나리오를 균형 있게 유지해 최악의 경우에도 로그 시간에 가운데값을 재조정합니다.

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

풀이 2: MedianFinder.findMedian — Time: O(1) / Space: O(n)
복잡도
Time O(1)
Space O(n)

피드백: 상황에 따라 두 힙의 최댓값/최솟값을 활용해 상호 보완적으로 중간값을 계산합니다.

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# N is the number of elements added to the data stream.
# TC: O(log N) for addNum, O(1) for findMedian
# SC: O(N) - stores elements split into two heaps

import heapq


class MedianFinder:

def __init__(self):
self.small = [] # max-heap (store negative values)
self.large = [] # min-heap

def addNum(self, num: int) -> None:
heapq.heappush(self.small, -num)

if self.small and self.large and (-self.small[0] > self.large[0]):
val = -heapq.heappop(self.small)
heapq.heappush(self.large, val)

if len(self.small) > len(self.large) + 1:
val = -heapq.heappop(self.small)
heapq.heappush(self.large, val)

if len(self.large) > len(self.small):
val = heapq.heappop(self.large)
heapq.heappush(self.small, -val)

def findMedian(self) -> float:
if len(self.small) > len(self.large):
return float(-self.small[0])
return (-self.small[0] + self.large[0]) / 2.0
28 changes: 28 additions & 0 deletions insert-interval/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.

🏷️ 알고리즘 패턴 분석

insert-interval/dolphinflow86.py
# N is the number of intervals.
# TC: O(N) - single pass through intervals array
# SC: O(N) - stores result intervals list


class Solution:

    def insert(self, intervals, newInterval):
        result = []
        i = 0
        n = len(intervals)

        while i < n and intervals[i][1] < newInterval[0]:
            result.append(intervals[i])
            i += 1

        while i < n and intervals[i][0] <= newInterval[1]:
            newInterval[0] = min(newInterval[0], intervals[i][0])
            newInterval[1] = max(newInterval[1], intervals[i][1])
            i += 1

        result.append(newInterval)

        while i < n:
            result.append(intervals[i])
            i += 1

        return result
  • 패턴: Two Pointers, Greedy, Binary Search
  • 설명: 삽입하려는 구간과 기존 구간 배열을 스캔하며, 겹치지 않는 구간은 유지하고 겹치는 구간은 합쳐 하나의 구간으로 합치는 방식이다. 연속 탐색으로 정렬된 구간을 한 번의 순회로 처리하는 특징이 있다.

📊 시간/공간 복잡도 분석

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

피드백: 왼쪽, 중간, 오른쪽 파트를 순차적으로 처리하여 중복되는 구간을 하나의 구간으로 합칩니다.

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# N is the number of intervals.
# TC: O(N) - single pass through intervals array
# SC: O(N) - stores result intervals list


class Solution:

def insert(self, intervals, newInterval):
result = []
i = 0
n = len(intervals)

while i < n and intervals[i][1] < newInterval[0]:
result.append(intervals[i])
i += 1

while i < n and intervals[i][0] <= newInterval[1]:
newInterval[0] = min(newInterval[0], intervals[i][0])
newInterval[1] = max(newInterval[1], intervals[i][1])
i += 1

result.append(newInterval)

while i < n:
result.append(intervals[i])
i += 1

return result
32 changes: 32 additions & 0 deletions kth-smallest-element-in-a-bst/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.

🏷️ 알고리즘 패턴 분석

kth-smallest-element-in-a-bst/dolphinflow86.py
# H is the height of the BST, and K is the target rank.
# TC: O(H + K) - in-order traversal stops after visiting K elements
# SC: O(H) - stack memory for in-order traversal recursion/loop

# 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 kthSmallest(self, root, k: int) -> int:
        stack = []
        curr = root

        while curr or stack:
            while curr:
                stack.append(curr)
                curr = curr.left

            curr = stack.pop()
            k -= 1

            if k == 0:
                return curr.val

            curr = curr.right

        return -1
  • 패턴: Binary Search, Monotonic Stack, Hash Map / Hash Set
  • 설명: 이 코드는 이진 탐색 트리의 중위 순회를 이용해 k번째 원소를 찾는다(정렬된 순서를 얻기 위해). 스택을 이용한 비재귀 형태의 중위 순회는 특정 시점에서의 상태를 기록하기 위한 Monotonic Stack의 응용으로 볼 수 있으며, 이진 탐색 트리의 특성에 의존하므로 Binary Search의 맥락도 포함된다.

📊 시간/공간 복잡도 분석

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

피드백: BST의 성질을 이용해 왼쪽으로 내려가며 순서를 카운트합니다.

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# H is the height of the BST, and K is the target rank.
# TC: O(H + K) - in-order traversal stops after visiting K elements
# SC: O(H) - stack memory for in-order traversal recursion/loop

# 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 kthSmallest(self, root, k: int) -> int:
stack = []
curr = root

while curr or stack:
while curr:
stack.append(curr)
curr = curr.left

curr = stack.pop()
k -= 1

if k == 0:
return curr.val

curr = curr.right

return -1
26 changes: 26 additions & 0 deletions lowest-common-ancestor-of-a-binary-search-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.

🏷️ 알고리즘 패턴 분석

lowest-common-ancestor-of-a-binary-search-tree/dolphinflow86.py
# H is the height of the binary search tree.
# TC: O(H) - traverses down tree height
# SC: O(1) - uses iterative traversal without recursion stack

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None


class Solution:

    def lowestCommonAncestor(self, root, p, q):
        curr = root

        while curr:
            if p.val < curr.val and q.val < curr.val:
                curr = curr.left
            elif p.val > curr.val and q.val > curr.val:
                curr = curr.right
            else:
                return curr

        return None
  • 패턴: Binary Search, Two Pointers
  • 설명: 이 코드는 이진 탐색 트리에서 두 노드의 공통 조상을 찾기 위해 현재 노드 기준으로 p와 q의 값 비교를 통해 한 방향으로만 이동하는 방식으로 탐색한다. 트리의 높이에 비례하는 시간 복잡도이며, 상호 비교를 통한 목표 위치 탐색이 핵심이다.

📊 시간/공간 복잡도 분석

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

피드백: 현재 노드 값을 비교해 좌우로 내려가며 LCA를 찾습니다.

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# H is the height of the binary search tree.
# TC: O(H) - traverses down tree height
# SC: O(1) - uses iterative traversal without recursion stack

# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None


class Solution:

def lowestCommonAncestor(self, root, p, q):
curr = root

while curr:
if p.val < curr.val and q.val < curr.val:
curr = curr.left
elif p.val > curr.val and q.val > curr.val:
curr = curr.right
else:
return curr

return None
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# n is the number of nodes, and E is the number of edges.
# TC: O(V + E * alpha(V)) - near linear time with path compression Union-Find
# SC: O(V) - parent and rank arrays for Union-Find


class Solution:

def countComponents(self, n: int, edges) -> int:
parent = list(range(n))
rank = [1] * n

def find(node):
if parent[node] != node:
parent[node] = find(parent[node])
return parent[node]

def union(n1, n2):
p1, p2 = find(n1), find(n2)
if p1 == p2:
return 0

if rank[p1] > rank[p2]:
parent[p2] = p1
rank[p1] += rank[p2]
else:
parent[p1] = p2
rank[p2] += rank[p1]
return 1

components = n
for u, v in edges:
components -= union(u, v)

return components
44 changes: 44 additions & 0 deletions serialize-and-deserialize-binary-tree/dolphinflow86.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# N is the number of nodes in the binary tree.
# TC: O(N) - visits each node once during serialization and deserialization
# SC: O(N) - stores node values and recursion stack

# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None


class Codec:

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

def dfs(node):
if not node:
vals.append("N")
return
vals.append(str(node.val))
dfs(node.left)
dfs(node.right)

dfs(root)
return ",".join(vals)

def deserialize(self, data):
vals = data.split(",")
self.i = 0

def dfs():
if vals[self.i] == "N":
self.i += 1
return None

node = TreeNode(int(vals[self.i]))
self.i += 1
node.left = dfs()
node.right = dfs()
return node

return dfs()
Loading