diff --git a/longest-substring-without-repeating-characters/hi-rachel.py b/longest-substring-without-repeating-characters/hi-rachel.py index cdcb6aaf9..baee2e1d8 100644 --- a/longest-substring-without-repeating-characters/hi-rachel.py +++ b/longest-substring-without-repeating-characters/hi-rachel.py @@ -58,3 +58,29 @@ def lengthOfLongestSubstring(self, s: str) -> int: max_len = max(max_len, right - left + 1) return max_len + + +# HashMap 풀이 +def lengthOfLongestSubstring(s: str) -> int: + if not s: + return 0 + + left = 0 # 윈도우 시작점 + max_length = 0 # 최대 길이 + seen = {} # 문자의 마지막 등장 위치를 저장하는 해시맵 + + for right in range(len(s)): + char = s[right] + + # 현재 문자가 윈도우 내에 이미 존재하는 경우 + if char in seen and seen[char] >= left: + # 윈도우 시작점을 중복 문자 다음 위치로 이동 + left = seen[char] + 1 + + # 현재 문자의 위치 업데이트 + seen[char] = right + + # 현재 윈도우 길이와 최대 길이 비교 후 업데이트 + max_length = max(max_length, right - left + 1) + + return max_length diff --git a/number-of-islands/hi-rachel.py b/number-of-islands/hi-rachel.py new file mode 100644 index 000000000..f3fbf41f4 --- /dev/null +++ b/number-of-islands/hi-rachel.py @@ -0,0 +1,72 @@ +""" +https://leetcode.com/problems/number-of-islands/ + +Given an m x n 2D binary grid grid which represents a map of '1's (land) and '0's (water), return the number of islands. + +An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water. + + +Example 1: +Input: grid = [ + ["1","1","1","1","0"], + ["1","1","0","1","0"], + ["1","1","0","0","0"], + ["0","0","0","0","0"] +] +Output: 1 + +Example 2: +Input: grid = [ + ["1","1","0","0","0"], + ["1","1","0","0","0"], + ["0","0","1","0","0"], + ["0","0","0","1","1"] +] +Output: 3 + +Constraints: +m == grid.length +n == grid[i].length +1 <= m, n <= 300 +grid[i][j] is '0' or '1'. + +BFS 풀이 +TC: O(m * n) +SC: O(m * n) +""" + +from collections import deque +from typing import List + +class Solution: + def numIslands(self, grid: List[List[str]]) -> int: + ans = 0 + dx = [-1, 1, 0, 0] + dy = [0, 0, -1, 1] + rows = len(grid) + cols = len(grid[0]) + + def bfs(x, y): + queue = deque() + queue.append((x, y)) + grid[x][y] = 2 + + while queue: + x, y = queue.popleft() + for i in range(4): + nx = x + dx[i] + ny = y + dy[i] + if 0 <= nx < rows and 0 <= ny < cols: + if grid[nx][ny] == "1": + grid[nx][ny] = "2" + queue.append((nx, ny)) + + return True + + for i in range(rows): + for j in range(cols): + if grid[i][j] == "1": + if bfs(i, j): + ans += 1 + + return ans diff --git a/reverse-linked-list/hi-rachel.py b/reverse-linked-list/hi-rachel.py index 07d94f9c5..c5eeacec1 100644 --- a/reverse-linked-list/hi-rachel.py +++ b/reverse-linked-list/hi-rachel.py @@ -1,10 +1,6 @@ -# Definition for singly-linked list. -# class ListNode: -# def __init__(self, val=0, next=None): -# self.val = val -# self.next = next - """ +https://leetcode.com/problems/reverse-linked-list/ + 1. Stack 활용 (LIFO) - LinkedList의 모든 원소를 Stack에 넣고 꺼냄 TC: O(n) time @@ -16,6 +12,12 @@ SC: O(1) -> 변수를 포인터 2개만 사용 """ +# Definition for singly-linked list. +class ListNode: + def __init__(self, val=0, next=None): + self.val = val + self.next = next + # Stack 풀이 class Solution: def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: @@ -42,3 +44,27 @@ def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: curr.next = prev prev, curr = curr, temp_next return prev + + +""" +25/9/5 복습 + +링크드 리스트 뒤집기 +=> 노드를 옮기는 것이 아니라, next 포인터의 방향을 바꾸면 된다! + +TC: O(n) +SC: O(1) +""" +class Solution: + def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: + prev = None # 이전 노드 + curr = head # 현재 노드 + + while curr: + next_node = curr.next # 다음 노드 기억 + curr.next = prev # 현재 노드의 방향을 반대로 + prev = curr # 이전 노드를 한 칸 앞으로 + curr = next_node # 현재 노드를 다음으로 이동 + + # prev가 마지막 노드이자 새 head + return prev diff --git a/set-matrix-zeroes/hi-rachel.py b/set-matrix-zeroes/hi-rachel.py new file mode 100644 index 000000000..ca93bfa17 --- /dev/null +++ b/set-matrix-zeroes/hi-rachel.py @@ -0,0 +1,33 @@ +""" +https://leetcode.com/problems/set-matrix-zeroes/description/ + +Given an m x n integer matrix matrix, if an element is 0, set its entire row and column to 0's. +You must do it in place. + +TC: O(m * n) +SC: O(m + n), set 자료구조 사용 +""" + +class Solution: + def setZeroes(self, matrix: List[List[int]]) -> None: + """ + Do not return anything, modify matrix in-place instead. + """ + rows = len(matrix) + cols = len(matrix[0]) + + zero_rows = set() # 최대 m개의 행 인덱스 저장 + zero_cols = set() # 최대 n개의 열 인덱스 저장 + + # 0이 있는 위치 찾기 + for i in range(rows): + for j in range(cols): + if matrix[i][j] == 0: + zero_rows.add(i) + zero_cols.add(j) + + # 0이 있는 행과 열 모두 0으로 만들기 + for i in range(rows): + for j in range(cols): + if i in zero_rows or j in zero_cols: + matrix[i][j] = 0 diff --git a/unique-paths/hi-rachel.py b/unique-paths/hi-rachel.py new file mode 100644 index 000000000..d095906f4 --- /dev/null +++ b/unique-paths/hi-rachel.py @@ -0,0 +1,51 @@ +""" +https://leetcode.com/problems/unique-paths/description/ + +아래로 이동 혹은 (1, 0) +오른쪽 이동만 가능 (0, 1) + +m => rows, n = cols +로봇이 (0, 0)에서 (m-1, n-1)에 도착 가능한 unique paths 개수를 반환 + +풀이 시간: 16분 +처음에 어떻게 풀어야 할 줄 몰랐지만, 그림을 그려보며 누적 규칙을 찾음 (위, 왼쪽 값 더해나가기) +paths[i][j] = paths[i-1][j] + paths[i][j-1] + +TC: O(m * n) +SC: O(m * n) +""" + +class Solution: + def uniquePaths(self, m: int, n: int) -> int: + paths = [[0] * n for _ in range(m)] + paths[0][0] = 1 + + for i in range(m): + for j in range(n): + if i - 1 >= 0 and j - 1 >= 0: + paths[i][j] = paths[i - 1][j] + paths[i][j - 1] + else: + paths[i][j] = 1 + + return paths[m - 1][n - 1] + + +""" +공간 복잡도 최적화 풀이 - 복습 필요 +dp[i][j] = dp[i-1][j] + dp[i][j-1] +=> dp[j] = dp[j] + dp[j-1] + +TC: O(m * n) +SC: O(n) +""" + +class Solution: + def uniquePaths(self, m: int, n: int) -> int: + # 첫 행은 모두 1로 초기화 + dp = [1] * n + + for i in range(1, m): + for j in range(1, n): + dp[j] = dp[j] + dp[j - 1] + + return dp[-1]