-
-
Notifications
You must be signed in to change notification settings - Fork 362
[alphaorderly] WEEK 07 Solutions #2793
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
4d5f428
3ac63f5
2536209
612dbbb
a7c2098
79f6f86
3855235
33ab6bc
b1de0e1
f9bf16c
de3390f
b3dc7d7
17669b6
d8b5903
a14205b
b087a32
2380e81
e51ae37
9592367
555e26d
9b11b3c
aeffd8e
9fb334a
cad3e9b
5d805dd
d64aecd
f9db228
266bdae
bff71b4
4a6924f
054781c
4e6a737
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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 |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
풀이 1:
|
| 복잡도 | |
|---|---|
| Time | O(m * n) |
| Space | O(m * n) |
피드백: BFS 구현은 큐를 사용하여 인접한 땅을 순차적으로 방문하며 방문 표시를 남깁니다.
개선 제안: 현재 구현이 적절해 보입니다.
풀이 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 |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 @@ | ||
| """ | ||
| 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 |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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,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 |
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
풀이 1:
|
| 복잡도 | |
|---|---|
| Time | O(m * n) |
| Space | O(m * n) |
피드백: 초기화와 점화식으로 모든 경로를 누적합니다. 2D DP 버전과 1D DP 버전이 함께 제시되어 있음.
개선 제안: 현재 구현이 적절해 보입니다.
풀이 2: Solution.uniquePaths — Time: O(m * n) / Space: O(n)
| 복잡도 | |
|---|---|
| Time | O(m * n) |
| Space | O(n) |
피드백: 공간 복잡도를 줄인 버전으로 동일한 시간 복잡도를 가집니다.
개선 제안: 현재 구현이 적절해 보입니다.
풀이 3: Solution.uniquePaths — Time: O(m + n) / Space: O(1)
| 복잡도 | |
|---|---|
| Time | O(m + n) |
| Space | O(1) |
피드백: 경로의 수를 조합으로 계산하는 방법으로 상수 공간에서 빠른 해를 제공합니다.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
There was a problem hiding this comment.
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 연산으로 하셔도 맨 아래 코드를 얻을수 있으세요!
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| """ | ||
| 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 = [[0 for _ in range(n)] for _ in range(m)] | ||
|
|
||
| for i in range(m): | ||
| for j in range(n): | ||
| if i == 0 or j == 0: | ||
| maze[i][j] = 1 | ||
| else: | ||
| 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(1, m): | ||
| 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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 해당 코드는 문자 등장 횟수를 카운트하는 해시맵을 사용해 중복 여부를 확인하고, 왼쪽 포인터를 이동시키며 윈도우를 유지합니다.
개선 제안: 현재 구현이 적절해 보입니다.