diff --git a/longest-substring-without-repeating-characters/liza0525.py b/longest-substring-without-repeating-characters/liza0525.py new file mode 100644 index 0000000000..20c8cb8f08 --- /dev/null +++ b/longest-substring-without-repeating-characters/liza0525.py @@ -0,0 +1,22 @@ +# 7기 풀이 +# 시간 복잡도: O(n) +# - 슬라이딩 윈도우 기법을 사용, s의 길이 n에 비례 +# 공간 복잡도: O(min(n, k)) +# - 중복 문자를 저장 및 체크할 char_set의 최대 크기인 k(s의 모든 문자가 중복하지 않을 때)와 s의 크기 n 중 작은 쪽 +class Solution: + def lengthOfLongestSubstring(self, s: str) -> int: + max_len = 0 + left = 0 # 왼쪽 포인터 지정 + char_set = set() # 중복 문자 체크를 위한 set 추가 + + # right를 하나씩 옮겨가며 문자열 길이를 체크, + for right in range(len(s)): + while s[right] in char_set: + # 중복 문자가 생길 경우 left를 움직이되, 중복된 문자 이전의 모든 문자를 제한다. + char_set.remove(s[left]) + left += 1 + + char_set.add(s[right]) # 현재의 문자인 s[right]를 char_set에 저장하여 다음 루프에 중복 체크를 하도록 한다. + max_len = max(max_len, right - left + 1) # 현재까지의 가장 긴 문자열을 계산하여 max_len 업데이트 + + return max_len diff --git a/number-of-islands/liza0525.py b/number-of-islands/liza0525.py new file mode 100644 index 0000000000..db6a2b86f3 --- /dev/null +++ b/number-of-islands/liza0525.py @@ -0,0 +1,34 @@ +# 7기 풀이 +# 시간 복잡도: O(n * m) +# - grid의 크기 n * m 에 따라 시간 복잡도가 정해짐(최악은 모든 grid 인덱스를 다 돌 때) +# 공간 복잡도: O(n * m) +# - 재귀 호출 스택의 최대 크기는 grid 이차 배열의 크기와 동일 +class Solution: + def numIslands(self, grid: List[List[str]]) -> int: + len_i, len_j = len(grid), len(grid[0]) + directions = [(1, 0), (-1, 0), (0, -1), (0 , 1)] # 탐색 방향(위, 아래, 왼쪽, 오른쪽 순) + + res = 0 + + def dfs(i, j): + grid[i][j] = "0" # 방문을 했으면 grid의 값을 "0"으로 변경해 다음 탐색 시 다시 방문하지 않도록 함 + for dir_i, dir_j in directions: + next_i, next_j = i + dir_i, j + dir_j + + # 다음 탐색 인덱스가 배열 범위 내이면서 + # grid[next_i][next_j]가 "1"이어야 그 다음 방문을 할 수 있다. + if ( + 0 <= next_i < len_i + and 0 <= next_j < len_j + and grid[next_i][next_j] == "1" + ): + dfs(next_i, next_j) + + for i in range(len_i): + for j in range(len_j): + if grid[i][j] == "0": # grid가 "0"일 땐 섬이 아니므로 탐색하지 않는다. + continue + dfs(i, j) # 섬 찾기 + res += 1 # 섬을 다 찾은 후엔 res에 1을 추가한다. + + return res diff --git a/reverse-linked-list/liza0525.py b/reverse-linked-list/liza0525.py index 22373de61c..a62bf3a2fc 100644 --- a/reverse-linked-list/liza0525.py +++ b/reverse-linked-list/liza0525.py @@ -6,3 +6,31 @@ def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: curr_node.next = pre_node pre_node, curr_node = curr_node, temp return pre_node + + +# 7기 풀이 +# 시간 복잡도: O(n) +# - 링크드 리스트의 길이만큼 탐색 +# 공간 복잡도: O(1) +# - 결과 변수 이외에는 curr_node 변수만 사용 +class Solution: + def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: + prev_node, curr_node = None, head + + while curr_node: + # next를 먼저 저장해두지 않으면 링크를 끊은 뒤 다음 노드를 잃어리므로 temp에 저장 + temp = curr_node.next + + # curr_node의 다음 노드로 prev_node를 저장 + curr_node.next = prev_node + + # prev_node와 curr_node에 각각 curr_node와 temp 노드를 저장하여 순서 바꾸기 + prev_node, curr_node = curr_node, temp + + return prev_node + +# Definition for singly-linked list. +# class ListNode: +# def __init__(self, val=0, next=None): +# self.val = val +# self.next = next diff --git a/unique-paths/liza0525.py b/unique-paths/liza0525.py new file mode 100644 index 0000000000..d04eb25a69 --- /dev/null +++ b/unique-paths/liza0525.py @@ -0,0 +1,16 @@ +# 7기 풀이 +# 시간 복잡도: O(m * n) +# - m과 n 만큼의 이중 루프를 돌게 됨 +# 공간 복잡도: O(m) +# - dp의 결과 값을 저장할 배열의 길이는 m의 길이에 좌우됨 +class Solution: + def uniquePaths(self, m: int, n: int) -> int: + # 이전 열의 값만 필요로 하기 때문에 1차원 배열을 사용하며 in-place 업데이트를 하면 된다. + dp = [1 for _ in range(m)] + + for _ in range(n - 1): + for i in range(1, m): + # 현재 칸 = 위에서 오는 경로 수(갱신 전 dp[i]) + 왼쪽에서 오는 경로 수(dp[i-1]) + dp[i] = dp[i] + dp[i - 1] + + return dp[m - 1] # 모든 루프를 돌고 나면 도착지 도달 가능 방법수가 저장이 되어 있다.