From 65fe9dfae03a9b0c329b6f371f1628b3b3dcf4b3 Mon Sep 17 00:00:00 2001 From: "Dahm-won (Abby) Heo" Date: Sat, 26 Apr 2025 22:36:23 +0900 Subject: [PATCH 1/6] week 4 week 4 --- coin-change/taurus09318976.py | 46 ++++++++++++ .../taurus09318976.py | 75 +++++++++++++++++++ .../taurus09318976.py | 58 ++++++++++++++ merge-two-sorted-lists/taurus09318976.py | 68 +++++++++++++++++ word-search/taurus09318976.py | 62 +++++++++++++++ 5 files changed, 309 insertions(+) create mode 100644 coin-change/taurus09318976.py create mode 100644 find-minimum-in-rotated-sorted-array/taurus09318976.py create mode 100644 maximum-depth-of-binary-tree/taurus09318976.py create mode 100644 merge-two-sorted-lists/taurus09318976.py create mode 100644 word-search/taurus09318976.py diff --git a/coin-change/taurus09318976.py b/coin-change/taurus09318976.py new file mode 100644 index 000000000..476c2abff --- /dev/null +++ b/coin-change/taurus09318976.py @@ -0,0 +1,46 @@ +''' +이 문제는 동적 프로그래밍을 이용한 방식이 +1) 모든 가능한 경우를 체계적으로 계산할 수 있고, +2) 중복 계산을 피할 수 있고, +3) 최적의 값을 보장한다는 점에서 좋은 풀이방식임. +다만, +1) amount가 클 경우 메모리 사용이 많을 수 있고, +2) 동전의 가치가 매우 작을 경우 시간이 오래 걸릴 수 있다는 점에서 단점이 있음 +''' + +class Solution: + def coinChange(self, coins: List[int], amount: int) -> int: + # 초기화 + # dp 배열: 각 금액을 만들기 위한 최소 동전 수를 저장 + # amount + 1로 초기화 (불가능한 경우를 구분하기 위해) + # 0원을 만들기 위한 동전 수는 0 + dp = [amount + 1] * (amount + 1) + dp[0] = 0 + + # 동적 프로그래밍 실행: + # 1원부터 amount원까지 순차적으로 계산 + for i in range(1, amount + 1): + # 각 동전에 대해 시도 + for coin in coins: + # 현재 금액이 동전보다 크거나 같은 경우에만 시도 + if i >= coin: + # 현재 동전을 사용하는 경우와 사용하지 않는 경우 중 최소값 선택 + dp[i] = min(dp[i], dp[i - coin] + 1) + + # 결과 반환 + # amount원을 만들 수 없는 경우 -1 반환 + return dp[amount] if dp[amount] != amount + 1 else -1 + + # 시간 복잡도 (Time Complexity): O(n * m) + #n: amount + #m: coins의 길이 + #이유: + #amount까지의 모든 금액에 대해 계산 + #각 금액마다 모든 동전을 확인 + #따라서 시간 복잡도는 O(n * m) + # 공간 복잡도 (Space Complexity): O(n) + # n: amount + #이유: + # dp 배열의 크기가 amount + 1 + # 추가적인 메모리 사용 없음 + # 따라서 공간 복잡도는 O(n) \ No newline at end of file diff --git a/find-minimum-in-rotated-sorted-array/taurus09318976.py b/find-minimum-in-rotated-sorted-array/taurus09318976.py new file mode 100644 index 000000000..c4b7ce383 --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/taurus09318976.py @@ -0,0 +1,75 @@ +# 백트래킹 방법을 사용하여 풀이함 +class Solution: + def exist(self, board: List[List[str]], word: str) -> bool: + # 보드의 행과 열 수 + rows, cols = len(board), len(board[0]) + # 방문한 셀을 추적하는 집합 + visited = set() + + # 깊이우선 탐색(DFS) 함수 정의 + #r, c은 현재 셀의 행과 열, i는 현재 찾고 있는 단어의 인덱스 + def dfs(r, c, i): + #기본 조건 확인 + # 단어의 모든 문자를 찾은 경우 성공 + if i == len(word): + return True + + #윺효성 검사 + # 범위를 벗어나거나 이미 방문했거나 현재 셀의 문자가 단어의 현재 문자와 일치하지 않는 경우 + if (r < 0 or c < 0 or + r >= rows or c >= cols or + (r, c) in visited or + board[r][c] != word[i]): + return False + + # 현재 셀을 방문했다고 표시 + visited.add((r, c)) + + # 상하좌우 방향으로 탐색 + result = (dfs(r + 1, c, i + 1) or # 아래 + dfs(r - 1, c, i + 1) or # 위 + dfs(r, c + 1, i + 1) or # 오른쪽 + dfs(r, c - 1, i + 1)) # 왼쪽 + + # 백트래킹: 현재 셀을 방문하지 않은 것으로 표시 + #현재 경로가 실패했으므로 방문 표시 제거 + visited.remove((r, c)) + + return result + + # 보드의 모든 셀에서 시작점으로 시도 + for r in range(rows): + for c in range(cols): + if dfs(r, c, 0): + return True + + return False + + #시간 복잡도 (Time Complexity): O(m * n * 4^L) + #m: 보드의 행 수 + #n: 보드의 열 수 + #L: 단어의 길이 + #이유: + #각 셀에서 시작할 수 있음: O(m * n) + #각 위치에서 4방향으로 탐색 가능: O(4^L) + #최악의 경우 모든 경로를 탐색해야 함 + #따라서 시간 복잡도는 O(m * n * 4^L) + #공간 복잡도 (Space Complexity): O(L) + #L: 단어의 길이 + #이유: + #재귀 호출 스택의 깊이는 단어의 길이에 비례 + #visited 집합의 크기도 단어의 길이에 비례 + #따라서 공간 복잡도는 O(L) + #DFS vs BFS 비교: + #DFS (깊이 우선 탐색): + #한 경로를 끝까지 탐색 + #스택/재귀 사용 + #메모리 사용이 적음 + #최단 경로 보장하지 않음 + #BFS (너비 우선 탐색): + #같은 레벨의 모든 노드를 먼저 탐색 + #큐 사용 + #메모리 사용이 많음 + #최단 경로 보장 + + diff --git a/maximum-depth-of-binary-tree/taurus09318976.py b/maximum-depth-of-binary-tree/taurus09318976.py new file mode 100644 index 000000000..e57803a03 --- /dev/null +++ b/maximum-depth-of-binary-tree/taurus09318976.py @@ -0,0 +1,58 @@ +# Definition for a binary tree node. +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def maxDepth(self, root: TreeNode) -> int: + # 루트가 None이면 깊이는 0 + if not root: + return 0 + + # 왼쪽 서브트리와 오른쪽 서브트리의 최대 깊이를 재귀적으로 계산 + left_depth = self.maxDepth(root.left) + right_depth = self.maxDepth(root.right) + + # 현재 노드의 깊이(1) + 왼쪽과 오른쪽 중 더 큰 깊이 + return 1 + max(left_depth, right_depth) + +# 테스트 코드 +def create_binary_tree(lst): + if not lst: + return None + + root = TreeNode(lst[0]) + queue = [root] + i = 1 + + while queue and i < len(lst): + current = queue.pop(0) + + if lst[i] is not None: + current.left = TreeNode(lst[i]) + queue.append(current.left) + i += 1 + + if i < len(lst) and lst[i] is not None: + current.right = TreeNode(lst[i]) + queue.append(current.right) + i += 1 + + return root + +# 테스트 케이스 +solution = Solution() + +# 테스트 케이스 1: [3,9,20,None,None,15,7] +tree1 = create_binary_tree([3,9,20,None,None,15,7]) +print(solution.maxDepth(tree1)) # 3 출력 + +# 테스트 케이스 2: [1,None,2] +tree2 = create_binary_tree([1,None,2]) +print(solution.maxDepth(tree2)) # 2 출력 + +# 테스트 케이스 3: [] +tree3 = create_binary_tree([]) +print(solution.maxDepth(tree3)) # 0 출력 \ No newline at end of file diff --git a/merge-two-sorted-lists/taurus09318976.py b/merge-two-sorted-lists/taurus09318976.py new file mode 100644 index 000000000..dc9f890d3 --- /dev/null +++ b/merge-two-sorted-lists/taurus09318976.py @@ -0,0 +1,68 @@ +# Definition for singly-linked list. +class ListNode: + def __init__(self, val=0, next=None): + self.val = val + self.next = next + +class Solution: + def mergeTwoLists(self, list1: ListNode, list2: ListNode) -> ListNode: + # 더미 노드 생성 + dummy = ListNode() + current = dummy + + # 두 리스트가 모두 존재하는 동안 반복 + while list1 and list2: + if list1.val <= list2.val: + current.next = list1 + list1 = list1.next + else: + current.next = list2 + list2 = list2.next + current = current.next + + # 남은 노드들 연결 + if list1: + current.next = list1 + else: + current.next = list2 + + return dummy.next + +# 테스트 코드 +def create_linked_list(lst): + if not lst: + return None + head = ListNode(lst[0]) + current = head + for val in lst[1:]: + current.next = ListNode(val) + current = current.next + return head + +def linked_list_to_list(head): + result = [] + while head: + result.append(head.val) + head = head.next + return result + +# 테스트 케이스 +solution = Solution() + +# 테스트 케이스 1 +list1 = create_linked_list([1,2,4]) +list2 = create_linked_list([1,3,4]) +result = solution.mergeTwoLists(list1, list2) +print(linked_list_to_list(result)) # [1,1,2,3,4,4] + +# 테스트 케이스 2 +list1 = create_linked_list([]) +list2 = create_linked_list([]) +result = solution.mergeTwoLists(list1, list2) +print(linked_list_to_list(result)) # [] + +# 테스트 케이스 3 +list1 = create_linked_list([]) +list2 = create_linked_list([0]) +result = solution.mergeTwoLists(list1, list2) +print(linked_list_to_list(result)) # [0] diff --git a/word-search/taurus09318976.py b/word-search/taurus09318976.py new file mode 100644 index 000000000..82b15674e --- /dev/null +++ b/word-search/taurus09318976.py @@ -0,0 +1,62 @@ +# 백트래킹 방법을 사용하여 풀이함 +class Solution: + def exist(self, board: List[List[str]], word: str) -> bool: + # 보드의 행과 열 수 + rows, cols = len(board), len(board[0]) + # 방문한 셀을 추적하는 집합 + visited = set() + + # 깊이우선 탐색(DFS) 함수 정의 + #r, c은 현재 셀의 행과 열, i는 현재 찾고 있는 단어의 인덱스 + def dfs(r, c, i): + #기본 조건 확인 + # 단어의 모든 문자를 찾은 경우 성공 + if i == len(word): + return True + + #윺효성 검사 + # 범위를 벗어나거나 이미 방문했거나 현재 셀의 문자가 단어의 현재 문자와 일치하지 않는 경우 + if (r < 0 or c < 0 or + r >= rows or c >= cols or + (r, c) in visited or + board[r][c] != word[i]): + return False + + # 현재 셀을 방문했다고 표시 + visited.add((r, c)) + + # 상하좌우 방향으로 탐색 + result = (dfs(r + 1, c, i + 1) or # 아래 + dfs(r - 1, c, i + 1) or # 위 + dfs(r, c + 1, i + 1) or # 오른쪽 + dfs(r, c - 1, i + 1)) # 왼쪽 + + # 백트래킹: 현재 셀을 방문하지 않은 것으로 표시 + #현재 경로가 실패했으므로 방문 표시 제거 + visited.remove((r, c)) + + return result + + # 보드의 모든 셀에서 시작점으로 시도 + for r in range(rows): + for c in range(cols): + if dfs(r, c, 0): + return True + + return False + + #시간 복잡도 (Time Complexity): O(m * n * 4^L) + #m: 보드의 행 수 + #n: 보드의 열 수 + #L: 단어의 길이 + #이유: + #각 셀에서 시작할 수 있음: O(m * n) + #각 위치에서 4방향으로 탐색 가능: O(4^L) + #최악의 경우 모든 경로를 탐색해야 함 + #따라서 시간 복잡도는 O(m * n * 4^L) + #공간 복잡도 (Space Complexity): O(L) + #L: 단어의 길이 + #이유: + #재귀 호출 스택의 깊이는 단어의 길이에 비례 + #visited 집합의 크기도 단어의 길이에 비례 + #따라서 공간 복잡도는 O(L) \ No newline at end of file From 8ed7718398ef7af5ba9b1fc76380a78948e9f8bd Mon Sep 17 00:00:00 2001 From: "Dahm-won (Abby) Heo" Date: Sat, 26 Apr 2025 22:38:42 +0900 Subject: [PATCH 2/6] week4 week 4 --- coin-change/taurus09318976.py | 2 +- find-minimum-in-rotated-sorted-array/taurus09318976.py | 1 + maximum-depth-of-binary-tree/taurus09318976.py | 2 +- merge-two-sorted-lists/taurus09318976.py | 1 + word-search/taurus09318976.py | 2 +- 5 files changed, 5 insertions(+), 3 deletions(-) diff --git a/coin-change/taurus09318976.py b/coin-change/taurus09318976.py index 476c2abff..4008954ee 100644 --- a/coin-change/taurus09318976.py +++ b/coin-change/taurus09318976.py @@ -43,4 +43,4 @@ def coinChange(self, coins: List[int], amount: int) -> int: #이유: # dp 배열의 크기가 amount + 1 # 추가적인 메모리 사용 없음 - # 따라서 공간 복잡도는 O(n) \ No newline at end of file + # 따라서 공간 복잡도는 O(n) diff --git a/find-minimum-in-rotated-sorted-array/taurus09318976.py b/find-minimum-in-rotated-sorted-array/taurus09318976.py index c4b7ce383..380590e2d 100644 --- a/find-minimum-in-rotated-sorted-array/taurus09318976.py +++ b/find-minimum-in-rotated-sorted-array/taurus09318976.py @@ -73,3 +73,4 @@ def dfs(r, c, i): #최단 경로 보장 + diff --git a/maximum-depth-of-binary-tree/taurus09318976.py b/maximum-depth-of-binary-tree/taurus09318976.py index e57803a03..2b8a2dd75 100644 --- a/maximum-depth-of-binary-tree/taurus09318976.py +++ b/maximum-depth-of-binary-tree/taurus09318976.py @@ -55,4 +55,4 @@ def create_binary_tree(lst): # 테스트 케이스 3: [] tree3 = create_binary_tree([]) -print(solution.maxDepth(tree3)) # 0 출력 \ No newline at end of file +print(solution.maxDepth(tree3)) # 0 출력 diff --git a/merge-two-sorted-lists/taurus09318976.py b/merge-two-sorted-lists/taurus09318976.py index dc9f890d3..146b74aec 100644 --- a/merge-two-sorted-lists/taurus09318976.py +++ b/merge-two-sorted-lists/taurus09318976.py @@ -66,3 +66,4 @@ def linked_list_to_list(head): list2 = create_linked_list([0]) result = solution.mergeTwoLists(list1, list2) print(linked_list_to_list(result)) # [0] + diff --git a/word-search/taurus09318976.py b/word-search/taurus09318976.py index 82b15674e..bf0ffaf52 100644 --- a/word-search/taurus09318976.py +++ b/word-search/taurus09318976.py @@ -59,4 +59,4 @@ def dfs(r, c, i): #이유: #재귀 호출 스택의 깊이는 단어의 길이에 비례 #visited 집합의 크기도 단어의 길이에 비례 - #따라서 공간 복잡도는 O(L) \ No newline at end of file + #따라서 공간 복잡도는 O(L) From 64ad68ab151d8b434e45271ef2b710d99001925a Mon Sep 17 00:00:00 2001 From: "Dahm-won (Abby) Heo" Date: Sat, 26 Apr 2025 22:47:30 +0900 Subject: [PATCH 3/6] week4 week4 --- .../taurus09318976.py | 90 +++++++++---------- merge-two-sorted-lists/taurus09318976.py | 81 ++++++++--------- 2 files changed, 81 insertions(+), 90 deletions(-) diff --git a/maximum-depth-of-binary-tree/taurus09318976.py b/maximum-depth-of-binary-tree/taurus09318976.py index 2b8a2dd75..84e55cec5 100644 --- a/maximum-depth-of-binary-tree/taurus09318976.py +++ b/maximum-depth-of-binary-tree/taurus09318976.py @@ -1,58 +1,54 @@ -# Definition for a binary tree node. +# 이진 트리의 노드를 정의하는 클래스 class TreeNode: def __init__(self, val=0, left=None, right=None): - self.val = val - self.left = left - self.right = right + self.val = val # 노드의 값 + self.left = left # 왼쪽 자식 노드 + self.right = right # 오른쪽 자식 노드 + class Solution: def maxDepth(self, root: TreeNode) -> int: - # 루트가 None이면 깊이는 0 + # 초기 조건 확인. 트리가 비어 있는 경우 깊이는 0 if not root: return 0 - # 왼쪽 서브트리와 오른쪽 서브트리의 최대 깊이를 재귀적으로 계산 - left_depth = self.maxDepth(root.left) - right_depth = self.maxDepth(root.right) + # 큐에 루트 노드를 추가, 깊이를 0으로 초기화 + queue = [root] + depth = 0 - # 현재 노드의 깊이(1) + 왼쪽과 오른쪽 중 더 큰 깊이 - return 1 + max(left_depth, right_depth) - -# 테스트 코드 -def create_binary_tree(lst): - if not lst: - return None - - root = TreeNode(lst[0]) - queue = [root] - i = 1 + # 너비우선 탐색(BFS) 실행. 큐가 비어있지 않은 동안 반복 + while queue: + # 새로운 레벨 시작될 때마다 깊이 증가 + depth += 1 + # 현재 레벨의 노드 수 저장 + level_size = len(queue) + + # 현재 레벨의 모든 노드를 순차적으로 처리 + for _ in range(level_size): + # 큐에서 노드 하나 꺼내기 + node = queue.pop(0) + + # 자식 노드 처리. 다음 레벨의 노드들이 됨 + ## 왼쪽 자식이 있으면 큐에 추가 + if node.left: + queue.append(node.left) + ## 오른쪽 자식이 있으면 큐에 추가 + if node.right: + queue.append(node.right) - while queue and i < len(lst): - current = queue.pop(0) - - if lst[i] is not None: - current.left = TreeNode(lst[i]) - queue.append(current.left) - i += 1 - - if i < len(lst) and lst[i] is not None: - current.right = TreeNode(lst[i]) - queue.append(current.right) - i += 1 - - return root - -# 테스트 케이스 -solution = Solution() - -# 테스트 케이스 1: [3,9,20,None,None,15,7] -tree1 = create_binary_tree([3,9,20,None,None,15,7]) -print(solution.maxDepth(tree1)) # 3 출력 - -# 테스트 케이스 2: [1,None,2] -tree2 = create_binary_tree([1,None,2]) -print(solution.maxDepth(tree2)) # 2 출력 + # 최종 깊이 반환 + return depth -# 테스트 케이스 3: [] -tree3 = create_binary_tree([]) -print(solution.maxDepth(tree3)) # 0 출력 + #시간 복잡도 (Time Complexity): O(n) + #n: 트리의 총 노드 수 + #이유: + #각 노드를 정확히 한 번씩만 방문 + #각 노드에서의 연산(추가, 제거)은 상수 시간 + #따라서 전체 시간 복잡도는 O(n) + #공간 복잡도 (Space Complexity): O(n) + #최악의 경우: O(n) + #평균적인 경우: O(n/2) ≈ O(n) + #이유: + #큐에 저장되는 최대 노드 수는 트리의 최대 너비 + #완전 이진 트리의 경우 마지막 레벨에 약 n/2개의 노드가 있을 수 있음 + #따라서 공간 복잡도는 O(n) diff --git a/merge-two-sorted-lists/taurus09318976.py b/merge-two-sorted-lists/taurus09318976.py index 146b74aec..7e0723e2f 100644 --- a/merge-two-sorted-lists/taurus09318976.py +++ b/merge-two-sorted-lists/taurus09318976.py @@ -1,69 +1,64 @@ -# Definition for singly-linked list. +# 연결 리스트의 노드를 정의하는 클래스 class ListNode: def __init__(self, val=0, next=None): + # 노드의 값 self.val = val + # 다음 노드를 가리키는 포인터 self.next = next + class Solution: - def mergeTwoLists(self, list1: ListNode, list2: ListNode) -> ListNode: - # 더미 노드 생성 + def mergeTwoLists(self, list1: ListNode, list2: ListNode): + # 더미 노드 생성 - 결과 리스트의 시작점으로 사용 dummy = ListNode() + # 현재 위치를 추적하는 포인터 current = dummy - # 두 리스트가 모두 존재하는 동안 반복 + # 병합과정 : 두 리스트가 모두 존재하는 동안 반복, + # 작은 값을 가진 노드를 선택해 결과 리스트에 추가, + # 선택된 리스트의 포인터를 다음 노드로 이동 + # 결과 리스트의 포인터도 다음으로 이동 while list1 and list2: + # list 1의 값이 list2의 값보다 작거나 같은 경우 if list1.val <= list2.val: + # list1의 노드를 결과에 추가 current.next = list1 + #list1의 포인터를 다음 노드로 이동 list1 = list1.next else: + #list2의 노드를 결과에 추가 current.next = list2 + #list2의 포인터를 다음 노드로 이동 list2 = list2.next + #결과 리스트의 포인터를 다음으로 이동 current = current.next - # 남은 노드들 연결 + # 한 리스트가 끝나면 다른 리스트의 남은 노드들을 모두 연결 + ## list1에 남은 노드가 있으면 모두 연결 if list1: current.next = list1 + + ## list2에 남은 노드가 있으면 모두 연결 else: current.next = list2 - - return dummy.next - -# 테스트 코드 -def create_linked_list(lst): - if not lst: - return None - head = ListNode(lst[0]) - current = head - for val in lst[1:]: - current.next = ListNode(val) - current = current.next - return head -def linked_list_to_list(head): - result = [] - while head: - result.append(head.val) - head = head.next - return result - -# 테스트 케이스 -solution = Solution() - -# 테스트 케이스 1 -list1 = create_linked_list([1,2,4]) -list2 = create_linked_list([1,3,4]) -result = solution.mergeTwoLists(list1, list2) -print(linked_list_to_list(result)) # [1,1,2,3,4,4] + # 더미 노드의 다음 노드부터가 실제 결과 + return dummy.next -# 테스트 케이스 2 -list1 = create_linked_list([]) -list2 = create_linked_list([]) -result = solution.mergeTwoLists(list1, list2) -print(linked_list_to_list(result)) # [] -# 테스트 케이스 3 -list1 = create_linked_list([]) -list2 = create_linked_list([0]) -result = solution.mergeTwoLists(list1, list2) -print(linked_list_to_list(result)) # [0] +#시간 복잡도 (Time Complexity): O(n + m) + #n: list1의 길이 + #m: list2의 길이 + #이유: + #각 리스트의 모든 노드를 정확히 한 번씩만 방문 + #각 노드에서의 연산(비교, 연결)은 상수 시간 + #따라서 전체 시간 복잡도는 O(n + m) +#공간 복잡도 (Space Complexity): O(1) + #이유: + #추가적인 데이터 구조를 사용하지 않음 + #사용하는 변수: + #dummy: 상수 공간 + #current: 상수 공간 + #입력 크기와 관계없이 일정한 메모리만 사용 + #따라서 공간 복잡도는 O(1) From b6c074c48c5c0ca1ccb20a959c77fd949f543001 Mon Sep 17 00:00:00 2001 From: "Dahm-won (Abby) Heo" Date: Sun, 27 Apr 2025 00:00:55 +0900 Subject: [PATCH 4/6] week4 week --- word-search/taurus09318976.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/word-search/taurus09318976.py b/word-search/taurus09318976.py index bf0ffaf52..302894aa7 100644 --- a/word-search/taurus09318976.py +++ b/word-search/taurus09318976.py @@ -16,10 +16,12 @@ def dfs(r, c, i): #윺효성 검사 # 범위를 벗어나거나 이미 방문했거나 현재 셀의 문자가 단어의 현재 문자와 일치하지 않는 경우 - if (r < 0 or c < 0 or - r >= rows or c >= cols or - (r, c) in visited or - board[r][c] != word[i]): + # 범위 검사 + if r < 0 or r >= rows or c < 0 or c >= cols: + return False + + # 방문 및 문자 일치 검사 + if (r, c) in visited or board[r][c] != word[i]: return False # 현재 셀을 방문했다고 표시 @@ -60,3 +62,15 @@ def dfs(r, c, i): #재귀 호출 스택의 깊이는 단어의 길이에 비례 #visited 집합의 크기도 단어의 길이에 비례 #따라서 공간 복잡도는 O(L) + + #DFS vs BFS 비교: + #DFS (깊이 우선 탐색): + #한 경로를 끝까지 탐색 + #스택/재귀 사용 + #메모리 사용이 적음 + #최단 경로 보장하지 않음 + #BFS (너비 우선 탐색): + #같은 레벨의 모든 노드를 먼저 탐색 + #큐 사용 + #메모리 사용이 많음 + #최단 경로 보장 From e3ec00c9dbd7122543d99ce696ce7334e8f48b9d Mon Sep 17 00:00:00 2001 From: "Dahm-won (Abby) Heo" Date: Sun, 27 Apr 2025 00:07:19 +0900 Subject: [PATCH 5/6] Update taurus09318976.py --- word-search/taurus09318976.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/word-search/taurus09318976.py b/word-search/taurus09318976.py index 302894aa7..801e5c3d2 100644 --- a/word-search/taurus09318976.py +++ b/word-search/taurus09318976.py @@ -14,7 +14,7 @@ def dfs(r, c, i): if i == len(word): return True - #윺효성 검사 + #유효성 감사 # 범위를 벗어나거나 이미 방문했거나 현재 셀의 문자가 단어의 현재 문자와 일치하지 않는 경우 # 범위 검사 if r < 0 or r >= rows or c < 0 or c >= cols: From a1bf24aa180a5800f33243c5ce4d011d1ca01d56 Mon Sep 17 00:00:00 2001 From: "Dahm-won (Abby) Heo" Date: Sun, 27 Apr 2025 00:17:17 +0900 Subject: [PATCH 6/6] Update taurus09318976.py --- .../taurus09318976.py | 114 +++++++----------- 1 file changed, 46 insertions(+), 68 deletions(-) diff --git a/find-minimum-in-rotated-sorted-array/taurus09318976.py b/find-minimum-in-rotated-sorted-array/taurus09318976.py index 380590e2d..8438ddba0 100644 --- a/find-minimum-in-rotated-sorted-array/taurus09318976.py +++ b/find-minimum-in-rotated-sorted-array/taurus09318976.py @@ -1,76 +1,54 @@ -# 백트래킹 방법을 사용하여 풀이함 class Solution: - def exist(self, board: List[List[str]], word: str) -> bool: - # 보드의 행과 열 수 - rows, cols = len(board), len(board[0]) - # 방문한 셀을 추적하는 집합 - visited = set() + #findMin 메서드는 정수 리스트를 입력 받아 정수를 반환 + def findMin(self, nums: List[int]) -> int: + # 배열의 시작과 끝 인덱스 설정 + ## left는 배열의 시작 인덱스, right는 배열의 끝 인덱스. len(nums) - 1 + left, right = 0, len(nums) - 1 - # 깊이우선 탐색(DFS) 함수 정의 - #r, c은 현재 셀의 행과 열, i는 현재 찾고 있는 단어의 인덱스 - def dfs(r, c, i): - #기본 조건 확인 - # 단어의 모든 문자를 찾은 경우 성공 - if i == len(word): - return True - - #윺효성 검사 - # 범위를 벗어나거나 이미 방문했거나 현재 셀의 문자가 단어의 현재 문자와 일치하지 않는 경우 - if (r < 0 or c < 0 or - r >= rows or c >= cols or - (r, c) in visited or - board[r][c] != word[i]): - return False - - # 현재 셀을 방문했다고 표시 - visited.add((r, c)) - - # 상하좌우 방향으로 탐색 - result = (dfs(r + 1, c, i + 1) or # 아래 - dfs(r - 1, c, i + 1) or # 위 - dfs(r, c + 1, i + 1) or # 오른쪽 - dfs(r, c - 1, i + 1)) # 왼쪽 - - # 백트래킹: 현재 셀을 방문하지 않은 것으로 표시 - #현재 경로가 실패했으므로 방문 표시 제거 - visited.remove((r, c)) - - return result + #완전히 정렬되어 배열이 회전되지 않은 경우, 첫 번째 요소가 최소값 + if nums[left] < nums[right]: + return nums[left] - # 보드의 모든 셀에서 시작점으로 시도 - for r in range(rows): - for c in range(cols): - if dfs(r, c, 0): - return True + # 이진 탐색 실행 : left < right인 동안 반복되며, 검색 범위가 1개 이상의 요소를 포함할 때까지 계속됨 + while left < right: + # 중간 인덱스 계산 : 중간값과 오른쪽 끝값 비교 후, 비교 결과에 따라 검색 범위 조정 + mid = (left + right) // 2 + + # 중간값이 오른쪽 값보다 큰 경우 + # -> 최소값은 중간값 오른쪽에 있음 + if nums[mid] > nums[right]: + left = mid + 1 + # 중간값이 오른쪽 값보다 작거나 같은 경우 + # -> 최소값은 중간값 포함 왼쪽에 있음 + else: + right = mid - return False + # 최종적으로 찾은 최소값 반환 + return nums[left] + +# 테스트 코드 +print(Solution().findMin([3, 4, 5, 1, 2])) # 출력: 1 +print(Solution().findMin([4, 5, 6, 7, 0, 1, 2])) # 출력: 0 +print(Solution().findMin([1])) # 출력: 1 + + + #시간 복잡도 (Time Complexity): O(log n) + #이유: + #이진 탐색 알고리즘 사용 + #각 단계마다 검색 범위가 절반으로 줄어듦 + #n개의 요소를 log₂n 번의 비교로 검색 + #예시: + #n = 8: 최대 3번의 비교 (log₂8 = 3) + #n = 16: 최대 4번의 비교 (log₂16 = 4) + #따라서 시간 복잡도는 O(log n) + #공간 복잡도 (Space Complexity): O(1) + #이유: + #추가적인 데이터 구조 사용하지 않음 + #사용하는 변수: + #left, right, mid: 상수 개수의 정수 변수 + #입력 크기와 관계없이 일정한 메모리만 사용 + #따라서 공간 복잡도는 O(1) - #시간 복잡도 (Time Complexity): O(m * n * 4^L) - #m: 보드의 행 수 - #n: 보드의 열 수 - #L: 단어의 길이 - #이유: - #각 셀에서 시작할 수 있음: O(m * n) - #각 위치에서 4방향으로 탐색 가능: O(4^L) - #최악의 경우 모든 경로를 탐색해야 함 - #따라서 시간 복잡도는 O(m * n * 4^L) - #공간 복잡도 (Space Complexity): O(L) - #L: 단어의 길이 - #이유: - #재귀 호출 스택의 깊이는 단어의 길이에 비례 - #visited 집합의 크기도 단어의 길이에 비례 - #따라서 공간 복잡도는 O(L) - #DFS vs BFS 비교: - #DFS (깊이 우선 탐색): - #한 경로를 끝까지 탐색 - #스택/재귀 사용 - #메모리 사용이 적음 - #최단 경로 보장하지 않음 - #BFS (너비 우선 탐색): - #같은 레벨의 모든 노드를 먼저 탐색 - #큐 사용 - #메모리 사용이 많음 - #최단 경로 보장