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
5 changes: 4 additions & 1 deletion alien-dictionary/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.

🏷️ 알고리즘 패턴 분석

alien-dictionary/dolphinflow86.py
# C is total length of all words, U is number of unique alien letters (<= 26).
# TC: O(C) - comparing adjacent words and processing topological sort graph
# SC: O(1) - unique letters and adjacency list bounded by 26 characters

from collections import deque
from typing import List


class Solution:

    def alienOrder(self, words: List[str]) -> str:
        adj = {char: set() for word in words for char in word}
        indegree = {char: 0 for word in words for char in word}

        for i in range(len(words) - 1):
            w1, w2 = words[i], words[i + 1]
            min_len = min(len(w1), len(w2))

            if len(w1) > len(w2) and w1[:min_len] == w2[:min_len]:
                return ""

            for j in range(min_len):
                if w1[j] != w2[j]:
                    if w2[j] not in adj[w1[j]]:
                        adj[w1[j]].add(w2[j])
                        indegree[w2[j]] += 1
                    break

        queue = deque([char for char in indegree if indegree[char] == 0])
        result = []

        while queue:
            char = queue.popleft()
            result.append(char)

            for neighbor in adj[char]:
                indegree[neighbor] -= 1
                if indegree[neighbor] == 0:
                    queue.append(neighbor)

        if len(result) < len(indegree):
            return ""

        return "".join(result)

    alien_order = alienOrder
  • 패턴: BFS, Dynamic Programming, Topological Sort
  • 설명: 알고리즘은 문자 간 선후관계를 그래프로 만들고 위상 정렬(BFS 기반)을 통해 순서를 도출하는 패턴입니다. 사이클 여부를 확인하며 부분 순서를 얻는 구조로, 그래프 탐색과 위상 정렬의 결합으로 문제를 풉니다.

📊 시간/공간 복잡도 분석

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

풀이 1: Solution.alienOrder — Time: O(C) / Space: O(U + E)
복잡도
Time O(C)
Space O(U + E)

피드백: 모든 문자에 대해 간선과 진입차수를 계산하고, 위상정렬로 결과를 얻는다. 유효하지 않은 경우 빈 문자열을 반환한다.

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

풀이 2: Solution.buildTree — Time: O(N) / Space: O(N)
복잡도
Time O(N)
Space O(N)

피드백: 사전 순회 인덱스를 전역처럼 다루며 inorder 맵을 이용해 루트 위치를 빠르게 찾는다.

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

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

Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
# SC: O(1) - unique letters and adjacency list bounded by 26 characters

from collections import deque
from typing import List


class Solution:

def alienOrder(self, words) -> str:
def alienOrder(self, words: List[str]) -> str:
adj = {char: set() for word in words for char in word}
indegree = {char: 0 for word in words for char in word}

Expand Down Expand Up @@ -41,3 +42,5 @@ def alienOrder(self, words) -> str:
return ""

return "".join(result)

alien_order = alienOrder

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.

🏷️ 알고리즘 패턴 분석

construct-binary-tree-from-preorder-and-inorder-traversal/dolphinflow86.py
# N is the number of nodes in the binary tree.
# TC: O(N) - building hashmap takes O(N), and each node is visited once in O(1) time
# SC: O(N) - hashmap takes O(N) space, and recursion call stack takes O(H) up to O(N)

from typing import List, Optional


# 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 buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
        inorder_map = {val: idx for idx, val in enumerate(inorder)}
        preorder_idx = 0

        def build(left: int, right: int) -> Optional[TreeNode]:
            nonlocal preorder_idx

            if left > right:
                return None

            root_val = preorder[preorder_idx]
            root = TreeNode(root_val)
            preorder_idx += 1

            mid = inorder_map[root_val]

            root.left = build(left, mid - 1)
            root.right = build(mid + 1, right)

            return root

        return build(0, len(inorder) - 1)
  • 패턴: Divide and Conquer, Hash Map / Hash Set
  • 설명: 전위순회와 중위순회를 이용해 트리 재구성하는 문제로, 부분 트리 구간(left..right)을 분할해 재귀적으로 트리를 구성하는 방식이며, 중위순회 인덱스 매핑을 통해 빠르게 중위 구간 분할 위치를 찾는 해시 맵 패턴이 핵심입니다.

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# N is the number of nodes in the binary tree.
# TC: O(N) - building hashmap takes O(N), and each node is visited once in O(1) time
# SC: O(N) - hashmap takes O(N) space, and recursion call stack takes O(H) up to O(N)

from typing import List, Optional


# 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 buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
inorder_map = {val: idx for idx, val in enumerate(inorder)}
preorder_idx = 0

def build(left: int, right: int) -> Optional[TreeNode]:
nonlocal preorder_idx

if left > right:
return None

root_val = preorder[preorder_idx]
root = TreeNode(root_val)
preorder_idx += 1

mid = inorder_map[root_val]

root.left = build(left, mid - 1)
root.right = build(mid + 1, right)

return root

return build(0, len(inorder) - 1)
31 changes: 31 additions & 0 deletions longest-palindromic-substring/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.

🏷️ 알고리즘 패턴 분석

longest-palindromic-substring/dolphinflow86.py
# N is the length of the string s.
# TC: O(N^2) - expanding around each of the 2N - 1 possible centers takes up to O(N)
# SC: O(1) - constant auxiliary space tracking the start index and maximum length


class Solution:

    def longestPalindrome(self, s: str) -> str:
        if len(s) <= 1:
            return s

        start, max_len = 0, 0

        def expand(left: int, right: int) -> tuple[int, int]:
            while left >= 0 and right < len(s) and s[left] == s[right]:
                left -= 1
                right += 1
            return left + 1, right - left - 1

        for i in range(len(s)):
            # Odd length palindrome (center is i)
            l1, len1 = expand(i, i)
            if len1 > max_len:
                start, max_len = l1, len1

            # Even length palindrome (center is between i and i + 1)
            l2, len2 = expand(i, i + 1)
            if len2 > max_len:
                start, max_len = l2, len2

        return s[start:start + max_len]
  • 패턴: Two Pointers, Dynamic Programming
  • 설명: 가장 긴 팰린드롬 부분문자열을 양쪽으로 확장하며 중심을 기준으로 탐색하는 방식으로, 좌우 포인터를 이용해 가능 구간을 확장시키는 패턴과 연결됩니다. 이 알고리즘은 확장을 반복하며 최댓값을 갱신하는 구조로 동작합니다.

📊 시간/공간 복잡도 분석

복잡도
Time O(n^2)
Space O(1)

피드백: 중심 확장을 통해 모든 가능한 회문을 검사하므로 전체 시간 복잡도는 문자열 길이의 제곱에 비례합니다. 추가 공간은 상수 공간입니다.

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# N is the length of the string s.
# TC: O(N^2) - expanding around each of the 2N - 1 possible centers takes up to O(N)
# SC: O(1) - constant auxiliary space tracking the start index and maximum length


class Solution:

def longestPalindrome(self, s: str) -> str:
if len(s) <= 1:
return s

start, max_len = 0, 0

def expand(left: int, right: int) -> tuple[int, int]:
while left >= 0 and right < len(s) and s[left] == s[right]:
left -= 1
right += 1
return left + 1, right - left - 1

for i in range(len(s)):
# Odd length palindrome (center is i)
l1, len1 = expand(i, i)
if len1 > max_len:
start, max_len = l1, len1

# Even length palindrome (center is between i and i + 1)
l2, len2 = expand(i, i + 1)
if len2 > max_len:
start, max_len = l2, len2

return s[start:start + max_len]
21 changes: 21 additions & 0 deletions rotate-image/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.

🏷️ 알고리즘 패턴 분석

rotate-image/dolphinflow86.py
# N is the number of rows and columns in the matrix.
# TC: O(N^2) - reversing rows takes O(N^2) and transposing across diagonal takes O(N^2)
# SC: O(1) - in-place rotation with no extra memory allocation

from typing import List


class Solution:

    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        # 1. Flip vertically (reverse rows)
        matrix.reverse()

        # 2. Transpose across main diagonal
        n = len(matrix)
        for i in range(n):
            for j in range(i + 1, n):
                matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
  • 패턴: Two Pointers, Greedy, Dynamic Programming, Binary Search, Monotonic Stack, Hash Map / Hash Set, Backtracking, DFS, BFS, Divide and Conquer, Union Find, Trie, Bit Manipulation, Heap / Priority Queue, Sliding Window, Fast & Slow Pointers, Dynam ic Programming
  • 설명: 코드는 2차원 매트릭스 회전을 in-place로 수행하며, 먼저 행 반전(역순), 이후 대각선 반전(전치)을 수행한다. 이를 통해 공간 절약적 회전 알고리즘이 구현되며, 패턴은 주로 배열/매트릭스의 제어 흐름이 핵심이다.

📊 시간/공간 복잡도 분석

복잡도
Time O(n^2)
Space O(1)

피드백: 두 단계 모두 전체 행렬의 모든 원소를 한 번씩 다루므로 시간은 O(n^2), 추가 공간은 상수입니다.

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# N is the number of rows and columns in the matrix.
# TC: O(N^2) - reversing rows takes O(N^2) and transposing across diagonal takes O(N^2)
# SC: O(1) - in-place rotation with no extra memory allocation

from typing import List


class Solution:

def rotate(self, matrix: List[List[int]]) -> None:
"""
Do not return anything, modify matrix in-place instead.
"""
# 1. Flip vertically (reverse rows)
matrix.reverse()

# 2. Transpose across main diagonal
n = len(matrix)
for i in range(n):
for j in range(i + 1, n):
matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
34 changes: 34 additions & 0 deletions subtree-of-another-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.

🏷️ 알고리즘 패턴 분석

subtree-of-another-tree/dolphinflow86.py
# M and N are the number of nodes in root and subRoot trees respectively.
# TC: O(M * N) - in the worst case, is_same is checked for every node in root
# SC: O(H) - recursion stack memory bounded by the height of root tree (up to O(M))

from typing import Optional


# 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 isSubtree(self, root: Optional["TreeNode"], subRoot: Optional["TreeNode"]) -> bool:
        if not subRoot:
            return True
        if not root:
            return False

        def is_same(s: Optional["TreeNode"], t: Optional["TreeNode"]) -> bool:
            if not s and not t:
                return True
            if not s or not t or s.val != t.val:
                return False
            return is_same(s.left, t.left) and is_same(s.right, t.right)

        if is_same(root, subRoot):
            return True

        return self.isSubtree(root.left, subRoot) or self.isSubtree(root.right, subRoot)
  • 패턴: Depth-First Search, Backtracking
  • 설명: 루트 트리의 각 노드에서 서브트리와의 일치를 재귀적으로 검사하며, 서브트리 확인은 두 트리의 구조를 DFS로 비교합니다. 전체적으로 트리를 순차적으로 탐색하고 조건에 맞는 경우를 탐색하는 패턴이 보입니다.

📊 시간/공간 복잡도 분석

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

피드백: 브루트의 모든 노드에 대해 서브트리 비교를 수행하므로 최악의 경우 O(n*m) 시간, 재귀 깊이는 트리의 높이에 비례하는 공간을 사용합니다.

개선 제안: 검색 최적화를 위해 문자열화 비교나 해시를 활용한 방법으로 개선 가능.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# M and N are the number of nodes in root and subRoot trees respectively.
# TC: O(M * N) - in the worst case, is_same is checked for every node in root
# SC: O(H) - recursion stack memory bounded by the height of root tree (up to O(M))

from typing import Optional


# 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 isSubtree(self, root: Optional["TreeNode"], subRoot: Optional["TreeNode"]) -> bool:
if not subRoot:
return True
if not root:
return False

def is_same(s: Optional["TreeNode"], t: Optional["TreeNode"]) -> bool:
if not s and not t:
return True
if not s or not t or s.val != t.val:
return False
return is_same(s.left, t.left) and is_same(s.right, t.right)

if is_same(root, subRoot):
return True

return self.isSubtree(root.left, subRoot) or self.isSubtree(root.right, subRoot)
Loading