Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4d5f428
week 1
alphaorderly Jun 27, 2026
3ac63f5
[alphaorderly] WEEK 02 Solutions
alphaorderly Jun 28, 2026
2536209
Merge branch 'DaleStudy:main' into main
alphaorderly Jun 28, 2026
612dbbb
fix: description에 맞게 코드 수정
alphaorderly Jun 28, 2026
a7c2098
fix: 좀 더 간결하게 수정
alphaorderly Jun 29, 2026
79f6f86
Merge branch 'DaleStudy:main' into main
alphaorderly Jul 4, 2026
3855235
[alphaorderly] WEEK 03 Solutions
alphaorderly Jul 4, 2026
33ab6bc
Merge branch 'main' of https://github.com/alphaorderly/leetcode-study
alphaorderly Jul 4, 2026
b1de0e1
fix: 불필요한 코드 삭제
alphaorderly Jul 4, 2026
f9bf16c
fix: 줄바꿈 린트 문제 수정
alphaorderly Jul 4, 2026
de3390f
[alphaorderly] WEEK 03 Solutions
alphaorderly Jul 4, 2026
b3dc7d7
Merge branch 'main' of https://github.com/alphaorderly/leetcode-study
alphaorderly Jul 4, 2026
17669b6
fix: 린트 오류 수정
alphaorderly Jul 4, 2026
d8b5903
fix: 파이썬 내장함수 사용 코드 추가
alphaorderly Jul 4, 2026
a14205b
fix: valid-palindrome 문제에 투포인터 구현 답안 추가
alphaorderly Jul 4, 2026
b087a32
fix: 로직 가독성 수정
alphaorderly Jul 5, 2026
2380e81
Merge branch 'DaleStudy:main' into main
alphaorderly Jul 10, 2026
e51ae37
[alphaorderly] WEEK 04 Solutions - draft
alphaorderly Jul 10, 2026
9592367
Merge branch 'main' of https://github.com/alphaorderly/leetcode-study
alphaorderly Jul 10, 2026
555e26d
fix: 코드 가독성 향상
alphaorderly Jul 11, 2026
9b11b3c
Merge branch 'DaleStudy:main' into main
alphaorderly Jul 17, 2026
aeffd8e
[alphaorderly] WEEK 05 Solutions
alphaorderly Jul 17, 2026
9fb334a
trie 사용한 풀이법 추가
alphaorderly Jul 19, 2026
cad3e9b
fix: 코드 체크 실패 개선
alphaorderly Jul 19, 2026
5d805dd
주석 개선
alphaorderly Jul 19, 2026
d64aecd
fix: 힌트 수정
alphaorderly Jul 24, 2026
f9db228
[alphaorderly] WEEK 06 Solutions
alphaorderly Jul 25, 2026
266bdae
Merge branch 'main' of https://github.com/alphaorderly/leetcode-study
alphaorderly Jul 25, 2026
bff71b4
[alphaorderly] WEEK 06 Solutions
alphaorderly Jul 27, 2026
4a6924f
[alphaorderly] WEEK 06 Solutions
alphaorderly Jul 30, 2026
054781c
[alphaorderly] WEEK 07 Solutions
alphaorderly Aug 2, 2026
4e6a737
Merge branch 'DaleStudy:main' into main
alphaorderly Aug 2, 2026
df718e2
[alphaorderly] WEEK 07 Solutions
alphaorderly Aug 3, 2026
500a10e
[alphaorderly] WEEK 07 Solutions
alphaorderly Aug 3, 2026
85e0321
[alphaorderly] WEEK 07 Solutions
alphaorderly Aug 3, 2026
1d3d1e7
fix: 범위 수정
alphaorderly Aug 3, 2026
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
26 changes: 26 additions & 0 deletions longest-substring-without-repeating-characters/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.

🏷️ 알고리즘 패턴 분석

  • 패턴: Sliding Window, Hash Map / Hash Set
  • 설명: 두 포인터(left, right)로 연속 부분 문자열을 창/window로 확장 축소하며 서로 다른 문자만 남도록 중복 여부를 해시 맵으로 관리하는 방식이다. 이는 길이가 최대로 되는 모든 고유 부분 문자열을 찾는 일반적인 Sliding Window 패턴에 해당한다.

📊 시간/공간 복잡도 분석

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

피드백: 슬라이딩 윈도우와 해시맵(딕셔너리) 활용으로 각 문자 등장 여부를 관리한다. right 증가에 따라 중복이 생기면 left를 이동시키며 윈도우 크기를 조정한다.

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""
Time Complexity: O(n)
Space Complexity: O(n)

Approach:
- Use a defaultdict to track the count of each character in the current window.
- Maintain two pointers, 'left' and 'right', to represent the sliding window over the string.
- As we iterate over the string with 'right', increment the count for the current character.
- If a duplicate character appears in the window (count > 1), move the 'left' pointer forward and decrement counts until there are no duplicates.
- After adjusting, update 'ans' with the maximum length found for a window with all unique characters.
"""
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
count = defaultdict(int)
ans = left = 0

for right, val in enumerate(s):
count[val] += 1

while count[val] > 1:
count[s[left]] -= 1
left += 1

ans = max(ans, right - left + 1)

return ans
87 changes: 87 additions & 0 deletions number-of-islands/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.

🏷️ 알고리즘 패턴 분석

  • 패턴: Depth-First Search, Breadth-First Search, Hash Map / Hash Set
  • 설명: 코드는 BFS와 DFS 두 가지 방식으로 섬을 탐색하며, 방문 여부를 표시하기 위해 격자 데이터를 '#''로 바꿉니다. 두 구현 모두 인접한 땅을 탐색하고 섬의 수를 증가시키는 패턴을 보이며, 방문 관리에 추가 데이터 구조를 사용하지 않는 점에서 해시 맵/세트의 직접 사용은 보조적으로 판단됩니다.

📊 시간/공간 복잡도 분석

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

풀이 1: Solution.numIslands — Time: O(m * n) / Space: O(m * n)
복잡도
Time O(m * n)
Space O(m * n)

피드백: 두 가지 구현이 제시되어 있으며 모두 탐색으로 모든 육지('1')를 방문한다. 방문 여부를 표시하기 위해 grid를 변형하여 추가 공간을 사용하지 않는다.

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

풀이 2: Solution.numIslands — Time: O(m * n) / Space: O(m * n)
복잡도
Time O(m * n)
Space O(m * n)

피드백: 재귀를 이용한 DFS로 모든 연결된 육지를 탐색한다. 스택을 사용하는 구현과 동일한 시간/공간 복잡도다.

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"""
Time Complexity: O(m * n)
Space Complexity: O(m * n)

### BFS Approach ###

Approach:
- Use BFS to traverse all parts of each island in the grid.
- Employ a queue to process all adjacent land cells iteratively.
- Use a 'bound' helper function to check if a cell is within the grid bounds.
- In 'island_marker', mark visited '1's with '#' to avoid revisiting.
- For every cell in the grid, when a land cell ('1') is encountered, initiate BFS and increment the island count.
"""
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
DIR = [[0, 1], [1, 0], [-1, 0], [0, -1]]
ROW = len(grid)
COL = len(grid[0])

def bound(row: int, col: int) -> bool:
return 0 <= row < ROW and 0 <= col < COL

def island_marker(row: int, col: int) -> None:
q = deque([(row, col)])
grid[row][col] = "#"

while q:
r, c = q.popleft()

for dr, dc in DIR:
tr, tc = r + dr, c + dc

if not bound(tr, tc) or grid[tr][tc] != "1":
continue

grid[tr][tc] = "#"
q.append((tr, tc))

ans = 0

for r in range(ROW):
for c in range(COL):
if grid[r][c] == "1":
island_marker(r, c)
ans += 1

return ans

"""
Time Complexity: O(m * n)
Space Complexity: O(m * n)

### DFS Approach ###

Approach:
- Use DFS to traverse all parts of each island in the grid.
- Visitation is done recursively rather than with a stack, so stack comment is removed for clarity.
- Use a 'bound' helper function to check if a cell is within the grid bounds.
- In 'island_marker', mark visited '1's with '#' to avoid revisiting.
- For every cell in the grid, when a land cell ('1') is encountered, initiate DFS and increment the island count.
"""
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
DIR = [[0, 1], [1, 0], [-1, 0], [0, -1]]
ROW = len(grid)
COL = len(grid[0])

def bound(row: int, col: int) -> bool:
return 0 <= row < ROW and 0 <= col < COL

def island_marker(row: int, col: int) -> None:
grid[row][col] = '#'

for dr, dc in DIR:
tr, tc = row + dr, col + dc
if bound(tr, tc) and grid[tr][tc] == '1':
island_marker(tr, tc)

ans = 0

for r in range(ROW):
for c in range(COL):
if grid[r][c] == "1":
island_marker(r, c)
ans += 1

return ans
25 changes: 25 additions & 0 deletions reverse-linked-list/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.

🏷️ 알고리즘 패턴 분석

  • 패턴: Two Pointers, Linked List
  • 설명: 헤드와 프리브 포인터를 이용해 linked list를 역순으로 순회하며 노드 연결을 재설정하는 전형적인 투 포인터 기법. 공간 복잡도 O(1), 반복 구조로 리스트를 한 번 순회한다.

📊 시간/공간 복잡도 분석

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

피드백: 단일 포인터를 활용해 앞 노드와 현재 노드의 연결을 역전한다.

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""
Time Complexity: O(n)
Space Complexity: O(1)

- We use a while loop to traverse the linked list.
- We use a prev pointer to store the previous node.
- We use a head pointer to store the current node.
- We use a old_next pointer to store the next node.
- We use a prev, head = head, old_next to update the prev and head pointers.
- We return the prev pointer.
"""

class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next

class Solution:
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
prev = None

while head:
prev, head.next, head = head, prev, head.next

return prev
37 changes: 37 additions & 0 deletions set-matrix-zeroes/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.

🏷️ 알고리즘 패턴 분석

  • 패턴: Dynamic Programming, Greedy, Hash Map / Hash Set
  • 설명: 이 코드는 행/열의 플래그를 첫 행/열을 임시 저장소로 활용하는 방식으로 제로를 표시하는 패턴이다. 공간을 추가로 사용하지 않고 원래 배열의 행/열을 이용해 조건을 전파하므로 일반적으로 최적화된 탐색/표시 기법으로 분류된다.

📊 시간/공간 복잡도 분석

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

피드백: 첫 행/열을 마커로 활용하는 표준 최적화 방법을 택했다. 초기 상태를 따로 확인하여 경계 케이스를 처리한다.

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""
Time Complexity: O(m * n)
Space Complexity: O(1)

Approach:
- Use the first row and first column as markers to track which rows and columns should be zeroed.
- First, check if the original first row or first column should be zeroed by scanning them separately.
- Then, scan the rest of the matrix. If an element is zero, set its corresponding first row and first column positions to zero.
- Next, iterate through the matrix (excluding the first row and column) and set elements to zero if their corresponding first row or first column are zero.
- Finally, zero the first row and/or first column if initially flagged.
"""
class Solution:
def setZeroes(self, matrix: List[List[int]]) -> None:
ROW = len(matrix)
COL = len(matrix[0])

row_check = any(matrix[0][c] == 0 for c in range(COL))
col_check = any(matrix[r][0] == 0 for r in range(ROW))

for r in range(ROW):
for c in range(COL):
if matrix[r][c] == 0:
matrix[r][0] = 0
matrix[0][c] = 0

for r in range(1, ROW):
for c in range(1, COL):
if matrix[r][0] == 0 or matrix[0][c] == 0:
matrix[r][c] = 0

if row_check:
for c in range(COL):
matrix[0][c] = 0

if col_check:
for r in range(ROW):
matrix[r][0] = 0
74 changes: 74 additions & 0 deletions unique-paths/alphaorderly.py

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.

2D DP에서 dp 내용을 출력하고
대각선으로 보면 Pascal Triangle이 만들어집니다.
이것대로 Combination 연산으로 하셔도 맨 아래 코드를 얻을수 있으세요!

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.

🏷️ 알고리즘 패턴 분석

  • 패턴: Dynamic Programming, Combinatorial, Memoization
  • 설명: 다양한 구현에서 2D/1D DP를 이용한 최단 경로의 경우의 수를 계산하고, 재귀+캐시(메모이제이션) 패턴으로 중복 계산을 줄이는 사례가 포함되어 있습니다. 또한 재귀 기반의 상향식 DP를 보완하는 memoization 기법이 사용됩니다.

📊 시간/공간 복잡도 분석

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

풀이 1: Solution.uniquePaths — Time: O(m * n) / Space: O(m * n)
복잡도
Time O(m * n)
Space O(m * n)

피드백: 여러 접근 방식이 포함되어 있지만 각각의 구현은 서로 다른 공간/시간 특성을 가진다. 문제에 따라 선택적으로 사용할 수 있다.

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

풀이 2: Solution.uniquePaths — Time: O(m * n) / Space: O(n)
복잡도
Time O(m * n)
Space O(n)

피드백: 행마다 열의 경로를 누적 업데이트하여 공간을 줄인다.

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

풀이 3: Solution.uniquePaths — Time: O(1) / Space: O(1)
복잡도
Time O(1)
Space O(1)

피드백: 팩토리얼 기반의 조합 계산으로 시간 복잡도는 입력에 따라 달라지지만 일반적으로 상수 계수의 차이가 있다.

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

풀이 4: Solution.uniquePaths — Time: O(m * n) / Space: O(m * n)
복잡도
Time O(m * n)
Space O(m * n)

피드백: 재귀 기반의 방법으로 중복되는 부분 문제를 저장해 효율을 유지한다.

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""
Time Complexity: O(m * n)
Space Complexity: O(m * n)

Dynamic Programming (2D DP approach):
- Use a 2D array where maze[i][j] represents the number of unique paths to cell (i, j).
- Initialize the first row and first column with 1 (since there's only one way to reach each cell: only right moves for the first row or only down moves for the first column).
- For all other cells, maze[i][j] = maze[i-1][j] + maze[i][j-1] (sum of paths from the cell above and the cell to the left).
- Return maze[m-1][n-1] as the answer, which is the total number of unique paths.
"""
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
maze = [[1] * n for _ in range(m)]

for i in range(1, m):
for j in range(1, n):
maze[i][j] = maze[i - 1][j] + maze[i][j - 1]

return maze[m - 1][n - 1]

"""
Time Complexity: O(m * n)
Space Complexity: O(n)

Dynamic Programming (1D DP optimization):
- Use a 1D array dp of size n.
- dp[c] keeps track of the number of unique paths to column c in the current row.
- Initialize dp with 1s (the first row has only one way to reach each column).
- For every row from the second onward, update dp[c] = dp[c] + dp[c - 1] (add ways from the left neighbor to ways accumulated so far).
- Return dp[-1] as the answer, representing the number of unique paths to the bottom-right cell.
"""
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
dp = [1] * n

for _ in range(m - 1):
for c in range(1, n):
dp[c] += dp[c - 1]

return dp[-1]

"""
Time Complexity: O(m + n)
Space Complexity: O(1)

Combinatorial approach:
- The problem reduces to choosing (m-1) moves down from (m+n-2) total movements (or equivalently (n-1) moves right).
- The number of unique paths is given by the formula (m+n-2)! / [(m-1)! * (n-1)!], representing all possible orderings of down and right moves.
- Use the combinatorial (factorial) formula to compute the result efficiently.
"""
class Solution:
def uniquePaths(self, m: int, n: int) -> int:
return comb(m + n - 2, n - 1)

"""
Time Complexity: O(m * n)
Space Complexity: O(m * n)

### Top down dynamic programming (with memoization) ###

Approach:
- Use recursion with memoization (via functools.cache) to store the number of unique paths to (row, col).
- The recursive function dp(row, col) returns the number of unique paths from the top-left to (row, col).
- Base case: If row == 1 or col == 1, there's only one unique path.
- Otherwise, dp(row, col) = dp(row-1, col) + dp(row, col-1).
- The answer is dp(m, n), the number of unique paths to the bottom-right cell.
"""
class Solution:
@cache
def uniquePaths(self, m: int, n: int) -> int:
if m == 1 or n == 1:
return 1

return self.uniquePaths(m - 1, n) + self.uniquePaths(m, n - 1)
Loading