-
-
Notifications
You must be signed in to change notification settings - Fork 195
[KwonNayeon] Week 7 #931
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
[KwonNayeon] Week 7 #931
Changes from all commits
b98d68c
a69f666
7ed033d
ad39058
67d6e22
0c16934
69b05ea
d3c182a
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,37 @@ | ||
""" | ||
Constraints: | ||
- 0 <= s.length <= 5 * 10^4 | ||
- s consists of English letters, digits, symbols and spaces. | ||
|
||
Time Complexity: O(n) | ||
- 문자열을 한번만 순회 | ||
|
||
Space Complexity: O(n) | ||
- 딕셔너리에 문자와 인덱스 저장 | ||
|
||
풀이 방법: | ||
1. 슬라이딩 윈도우와 딕셔너리를 활용 | ||
2. seen 딕셔너리에 각 문자의 마지막 등장 위치를 저장 | ||
3. 중복 문자를 만나면 윈도우의 시작점(current_start)을 중복 문자 다음 위치로 이동 | ||
4. 매 단계에서 현재 윈도우의 길이를 계산하고 최대 길이 갱신 | ||
5. 최종적으로 가장 긴 중복 없는 부분 문자열의 길이 반환 | ||
""" | ||
|
||
class Solution: | ||
def lengthOfLongestSubstring(self, s: str) -> int: | ||
seen = {} | ||
current_start = 0 | ||
max_length = 0 | ||
|
||
for i in range(len(s)): | ||
char = s[i] | ||
|
||
if char in seen and seen[char] >= current_start: | ||
current_start = seen[char] + 1 | ||
|
||
seen[char] = i | ||
|
||
current_length = i - current_start + 1 | ||
max_length = max(current_length, max_length) | ||
|
||
return max_length |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
""" | ||
Constraints: | ||
- m == grid.length | ||
- n == grid[i].length | ||
- 1 <= m, n <= 300 | ||
- grid[i][j] is '0' or '1'. | ||
|
||
Time Complexity: O(m * n) | ||
- 모든 셀을 한 번씩 방문 | ||
- 여기서 m은 행, n은 열을 의미함 | ||
|
||
Space Complexity: O(m * n) | ||
- 최악의 경우(모든 셀이 '1'일 때) m * n 만큼의 재귀 호출 스택 사용 | ||
|
||
풀이 방법: | ||
1. 2중 for문으로 그리드의 모든 셀을 순회 | ||
2. '1'을 발견하면 DFS로 연결된 모든 땅을 방문하고 '0'으로 표시 | ||
3. '1'을 발견할 때마다 islands 카운트를 1씩 증가 | ||
""" | ||
|
||
class Solution: | ||
def numIslands(self, grid: List[List[str]]) -> int: | ||
islands = 0 | ||
for i in range(len(grid)): | ||
for j in range(len(grid[0])): | ||
if grid[i][j] == '1': | ||
self.visit_island(grid, i, j) | ||
islands += 1 | ||
return islands | ||
|
||
def visit_island(self, grid, i, j): | ||
if (i < 0 or i >= len(grid) or | ||
j < 0 or j >= len(grid[0]) or | ||
grid[i][j] != '1'): | ||
return | ||
|
||
grid[i][j] = '0' | ||
|
||
self.visit_island(grid, i+1, j) # 위 | ||
self.visit_island(grid, i-1, j) # 아래 | ||
self.visit_island(grid, i, j+1) # 오른쪽 | ||
self.visit_island(grid, i, j-1) # 왼쪽 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
""" | ||
Constraints: | ||
- The number of nodes in the list is the range [0, 5000] | ||
- -5000 <= Node.val <= 5000 | ||
|
||
Time Complexity: O(n) | ||
- n은 linked list의 노드 수 | ||
- 리스트를 한 번 순회하면서 각 노드를 한 번씩만 방문하기 때문 | ||
|
||
Space Complexity: O(1) | ||
- 추가 공간으로 prev, curr, temp 세 개의 포인터만 사용 | ||
- 입력 크기와 관계없이 일정한 추가 공간만 사용 | ||
|
||
풀이 방법: | ||
1. 세 개의 포인터를 사용하여 리스트를 순회하면서 뒤집기 | ||
- prev: 이전 노드를 가리키는 포인터 | ||
- curr: 현재 노드를 가리키는 포인터 | ||
- temp: 다음 노드를 임시 저장하는 포인터 | ||
|
||
2. 각 단계에서: | ||
- 다음 노드 임시 저장 (temp) | ||
- 현재 노드의 next를 이전 노드로 변경 | ||
- 포인터들을 한 칸씩 전진 | ||
|
||
3. 참고: | ||
- 포인터들의 이동 순서가 중요 | ||
- prev가 새로운 head가 됨 | ||
""" | ||
|
||
# Definition for singly-linked list. | ||
# 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 | ||
curr = head | ||
|
||
while curr is not None: | ||
|
||
temp = curr.next | ||
curr.next = prev | ||
prev = curr | ||
curr = temp | ||
|
||
return prev |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
""" | ||
Constraints: | ||
- m == matrix.length | ||
- n == matrix[0].length | ||
- 1 <= m, n <= 200 | ||
- -2^31 <= matrix[i][j] <= 2^31 - 1 | ||
|
||
Time Complexity: O(m*n) | ||
- m은 행, n은 열을 의미 | ||
- 0 찾기: O(m*n) | ||
- 행과 열 변환: O(m*n) | ||
|
||
Space Complexity: O(m*n) | ||
- zeros 배열이 최대 m*n 크기까지 저장 가능 | ||
|
||
풀이 방법: | ||
1. 0 위치 저장 | ||
2. 저장된 0의 행과 열을 모두 0으로 변환 | ||
3. 주의점: 행렬 값 탐색과 변경을 동시에 수행하면 원래 어떤 값이 0이었는지 구분하기 어려워짐 | ||
""" | ||
|
||
class Solution: | ||
def setZeroes(self, matrix: List[List[int]]) -> None: | ||
""" | ||
Do not return anything, modify matrix in-place instead. | ||
""" | ||
zeros = [] | ||
|
||
for r in range(len(matrix)): | ||
for c in range(len(matrix[0])): | ||
if matrix[r][c] == 0: | ||
zeros.append((r, c)) | ||
|
||
for r, c in zeros: | ||
for i in range(len(matrix[0])): | ||
matrix[r][i] = 0 | ||
for i in range(len(matrix)): | ||
matrix[i][c] = 0 | ||
|
||
""" | ||
Time Complexity: O(m*n) | ||
- 행렬 순회: O(m*n) | ||
- 행과 열 변환: O(m*n) | ||
|
||
Space Complexity: O(m+n) | ||
- zero_rows: O(m) | ||
- zero_cols: O(n) | ||
|
||
풀이 방법: | ||
1. set 자료구조를 활용하여 중복 제거 | ||
2. 행과 열 정보를 분리 저장하여 메모리를 효율적으로 사용 | ||
3. 행과 열을 독립적으로 처리하여 불필요한 반복 연산 제거 | ||
""" | ||
|
||
class Solution: | ||
def setZeroes(self, matrix: List[List[int]]) -> None: | ||
""" | ||
Do not return anything, modify matrix in-place instead. | ||
""" | ||
zero_rows = set() | ||
zero_cols = set() | ||
|
||
for r in range(len(matrix)): | ||
for c in range(len(matrix[0])): | ||
if matrix[r][c] == 0: | ||
zero_rows.add(r) | ||
zero_cols.add(c) | ||
|
||
for r in zero_rows: | ||
for i in range(len(matrix[0])): | ||
matrix[r][i] = 0 | ||
|
||
for c in zero_cols: | ||
for i in range(len(matrix)): | ||
matrix[i][c] = 0 | ||
|
||
""" | ||
Time Complexity: O(m*n) | ||
|
||
Space Complexity: O(1) | ||
- 추가적인 메모리를 사용하지 않고 첫 행과 열을 마커로 활용하여 해결 | ||
- first_row_zero, first_col_zero 두 변수만 사용 | ||
|
||
풀이 방법: | ||
1. 첫 행과 첫 열의 0 여부를 변수에 저장 (나중에 처리하기 위함) | ||
2. 첫 행과 첫 열을 마커로 사용: 행렬의 0 위치를 첫 행/열에 표시 | ||
3. 표시된 0을 기준으로 나머지 행렬을 변경 (행/열 전체를 0으로 변경) | ||
4. 저장해둔 변수로 첫 행/열 처리 (원래 0이었던 행/열 처리) | ||
""" | ||
class Solution: | ||
def setZeroes(self, matrix: List[List[int]]) -> None: | ||
# 첫 행/열의 0 여부 저장 | ||
first_row_zero = any(matrix[0][c] == 0 for c in range(len(matrix[0]))) | ||
first_col_zero = any(matrix[r][0] == 0 for r in range(len(matrix))) | ||
|
||
# 0이 있는 위치의 첫 행/열에 표시 | ||
for r in range(1, len(matrix)): | ||
for c in range(1, len(matrix[0])): | ||
if matrix[r][c] == 0: | ||
matrix[r][0] = 0 # 첫 열에 표시 | ||
matrix[0][c] = 0 # 첫 행에 표시 | ||
|
||
# 표시된 0을 기준으로 나머지 위치 변경 | ||
for r in range(1, len(matrix)): | ||
for c in range(1, len(matrix[0])): | ||
if matrix[r][0] == 0 or matrix[0][c] == 0: | ||
matrix[r][c] = 0 | ||
|
||
# 첫 행/열 처리 | ||
if first_row_zero: | ||
for i in range(len(matrix[0])): | ||
matrix[0][i] = 0 | ||
|
||
if first_col_zero: | ||
for i in range(len(matrix)): | ||
matrix[i][0] = 0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
""" | ||
Constraints: | ||
- 1 <= m, n <= 100 | ||
|
||
Time Complexity: O(1) | ||
- math.comb() 사용 | ||
|
||
Space Complexity: O(1) | ||
- 추가 공간 필요없음 | ||
|
||
풀이 방법: | ||
- 오른쪽 아래 코너로 가는 유니크한 방법의 갯수 찾기 | ||
1. (m-1)번 아래로, (n-1)번 오른쪽으로 가야함 -> 총 (m+n-2)번 이동 | ||
2. 결국 (m+n-2)번의 이동 중 (n-1)번의 오른쪽 이동을 선택하는 조합의 수 | ||
3. Combination 공식 적용: (m+n-2)C(n-1) | ||
|
||
Further Consideration: | ||
- DP로 풀어보기 | ||
""" | ||
class Solution: | ||
def uniquePaths(self, m: int, n: int) -> int: | ||
from math import comb | ||
return comb(m+n-2, n-1) | ||
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. 역시 파이썬..! 중요하지 않은 내용입니다. 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. @HC-kang 님 꼼꼼한 리뷰 감사합니다! 저도 내장 라이브러리를 활용한 방법 말고 다른 방법도 찾아봐야지... 생각만 하고 있었는데, 리뷰 달아주셨으니 다른 방법도 꼭 찾아봐야겠어요 😂👍 |
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.
공간복잡도를 개선하는 과정을 보여주시니 좋네요!
혹시 시간이 가능하시다면, 한번
O(1)
까지 확보해 보시는것은 어떨까요?이미 한단계 개선 스텝을 밟으셔서, 다음 스텝도 금방 찾으실수 있을 것 같아요!
약간의 힌트라면, 주어진 배열이 굳이
0
또는1
말고 잠깐 다른 값을 가져도 문제가 될건 없겠죠?