From 1fcdcfc149b51c09ba06aaf97e9fb739c87d93ed Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Tue, 4 Feb 2025 17:47:50 +0900 Subject: [PATCH 1/8] add solution: linked-list-cycle --- linked-list-cycle/dusunax.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 linked-list-cycle/dusunax.py diff --git a/linked-list-cycle/dusunax.py b/linked-list-cycle/dusunax.py new file mode 100644 index 000000000..e52345f1a --- /dev/null +++ b/linked-list-cycle/dusunax.py @@ -0,0 +1,33 @@ +''' +# 141. Linked List Cycle + +use two pointers, Floyd's Tortoise and Hare algorithm + +> Tortoise and Hare algorithm +>- slow pointer moves one step at a time +>- fast pointer moves two steps at a time +>- if there is a cycle, slow and fast will meet at some point +>- if there is no cycle, fast will reach the end of the list + +## Time Complexity: O(n) +In the worst case, we need to traverse the entire list to determine if there is a cycle. + +## Space Complexity: O(1) +no extra space is used, only the two pointers. +''' +class Solution: + def hasCycle(self, head: Optional[ListNode]) -> bool: + if not head or not head.next: + return False + + slow = head + fast = head + + while fast and fast.next: + slow = slow.next + fast = fast.next.next + + if slow == fast: + return True + + return False \ No newline at end of file From cf0eb3876fe5d40b81b60502fc7550c868ae6922 Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Wed, 5 Feb 2025 14:50:22 +0900 Subject: [PATCH 2/8] fix: add new line --- linked-list-cycle/dusunax.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linked-list-cycle/dusunax.py b/linked-list-cycle/dusunax.py index e52345f1a..333647c84 100644 --- a/linked-list-cycle/dusunax.py +++ b/linked-list-cycle/dusunax.py @@ -30,4 +30,4 @@ def hasCycle(self, head: Optional[ListNode]) -> bool: if slow == fast: return True - return False \ No newline at end of file + return False From 6e927c7cf6c7e9893b9a7d89311959cabcdc36da Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Thu, 6 Feb 2025 22:21:34 +0900 Subject: [PATCH 3/8] add solution: find-minimum-in-rotated-sorted-array --- find-minimum-in-rotated-sorted-array/dusunax.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 find-minimum-in-rotated-sorted-array/dusunax.py diff --git a/find-minimum-in-rotated-sorted-array/dusunax.py b/find-minimum-in-rotated-sorted-array/dusunax.py new file mode 100644 index 000000000..99265df4a --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/dusunax.py @@ -0,0 +1,15 @@ +''' +# 153. Find Minimum in Rotated Sorted Array + +## Time Complexity: O(n) +- min() iterates through all elements to find the smallest one. + +## Space Complexity: O(1) +- no extra space is used. +''' +class Solution: + def findMin(self, nums: List[int]) -> int: + if len(nums) == 1: + return nums[0] + + return min(nums) From ae76221875b7a3a39f8eec4171601ff562a4bda6 Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Thu, 6 Feb 2025 23:07:34 +0900 Subject: [PATCH 4/8] add-solution: pacific-atlantic-water-flow --- pacific-atlantic-water-flow/dusunax.py | 42 ++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 pacific-atlantic-water-flow/dusunax.py diff --git a/pacific-atlantic-water-flow/dusunax.py b/pacific-atlantic-water-flow/dusunax.py new file mode 100644 index 000000000..7588a41cd --- /dev/null +++ b/pacific-atlantic-water-flow/dusunax.py @@ -0,0 +1,42 @@ +''' +# 417. Pacific Atlantic Water Flow + +## Time Complexity: O(n * m) +- dfs is called for each cell in the grid, and each cell is visited once. + +## Space Complexity: O(n * m) +- pacific and atlantic sets store the cells that can flow to the pacific and atlantic oceans respectively. +''' +class Solution: + def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]: + if len(heights) == 1 and len(heights[0]) == 1: + return [[0, 0]] + + max_row, max_col = len(heights), len(heights[0]) + pacific, atlantic = set(), set() + directions = [(1, 0), (0, 1), (-1, 0), (0, -1)] + + def dfs(r, c, visited, prev_height): + out_of_bound = r < 0 or c < 0 or r >= max_row or c >= max_col + if out_of_bound: + return + + current = heights[r][c] + is_visited = (r, c) in visited + is_uphill = current < prev_height + if is_visited or is_uphill: + return + + visited.add((r, c)) + + for dr, dc in directions: + dfs(r + dr, c + dc, visited, current) + + for r in range(max_row): + dfs(r, 0, pacific, heights[r][0]) # left + dfs(r, max_col - 1, atlantic, heights[r][max_col - 1]) # right + for c in range(max_col): + dfs(0, c, pacific, heights[0][c]) # top + dfs(max_row - 1, c, atlantic, heights[max_row - 1][c]) # bottom + + return list(pacific & atlantic) From 985bf23d047ea688e5b128932be477a78eec41d2 Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Fri, 7 Feb 2025 07:02:46 +0900 Subject: [PATCH 5/8] update solution: find-minimum-in-rotated-sorted-array --- .../dusunax.py | 40 +++++++++++++++---- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/find-minimum-in-rotated-sorted-array/dusunax.py b/find-minimum-in-rotated-sorted-array/dusunax.py index 99265df4a..80241dbc2 100644 --- a/find-minimum-in-rotated-sorted-array/dusunax.py +++ b/find-minimum-in-rotated-sorted-array/dusunax.py @@ -1,15 +1,41 @@ ''' # 153. Find Minimum in Rotated Sorted Array -## Time Complexity: O(n) -- min() iterates through all elements to find the smallest one. - -## Space Complexity: O(1) -- no extra space is used. +> **why binary search works in a "rotated" sorted array?** +> rotated sorted array consists of **two sorted subarrays**, and the minimum value is the second sorted subarray's first element. +> so πŸ‘‰ find the point that second sorted subarray starts. +> +> - if nums[mid] > nums[right]? => the pivot point is in the right half. +> - if nums[mid] <= nums[right]? => the pivot point is in the left half. +> - loop until left and right are the same. ''' class Solution: - def findMin(self, nums: List[int]) -> int: + ''' + ## A. brute force(not a solution) + - TC: O(n) + - SC: O(1) + ''' + def findMinBF(self, nums: List[int]) -> int: if len(nums) == 1: return nums[0] - return min(nums) + return min(nums) # check all elements + + ''' + ## B. binary search + - TC: O(log n) + - SC: O(1) + ''' + def findMinBS(self, nums: List[int]) -> int: + left = 0 + right = len(nums) - 1 + + while left < right: + mid = (left + right) // 2 + + if nums[mid] > nums[right]: + left = mid + 1 + else: + right = mid + + return nums[left] From 187d1d2448644464184367af3c30449e7a75a832 Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Sat, 8 Feb 2025 22:17:41 +0900 Subject: [PATCH 6/8] add solution: maximum-product-subarray --- maximum-product-subarray/dusunax.py | 31 +++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 maximum-product-subarray/dusunax.py diff --git a/maximum-product-subarray/dusunax.py b/maximum-product-subarray/dusunax.py new file mode 100644 index 000000000..b8c3dcd74 --- /dev/null +++ b/maximum-product-subarray/dusunax.py @@ -0,0 +1,31 @@ +''' +# 152. Maximum Product Subarray + +solution reference: https://www.algodale.com/problems/maximum-product-subarray/ + +## μ΅œλŒ€ κ³± λ°°μ—΄ κ΅¬ν•˜κΈ° +- 연속 λ°°μ—΄(subarray)에 μ–‘μˆ˜, 음수, 0이 포함될 수 μžˆλ‹€. +- μŒμˆ˜κ°€ 결과에 영ν–₯을 λ―ΈμΉ  수 있기 λ•Œλ¬Έμ— μ΅œμ†Œκ°’/μ΅œλŒ€κ°’ 좔적이 ν•„μš”ν•˜λ‹€. + +## κ°’ +- result: μ΅œμ’…μ μœΌλ‘œ λ°˜ν™˜ν•  κ°’ +- min_prod: ν˜„μž¬κΉŒμ§€μ˜ μ΅œμ†Œ κ³± κ°’ (음수λ₯Ό κ³ λ €ν•œ 좔적) +- max_prod: ν˜„μž¬κΉŒμ§€μ˜ μ΅œλŒ€ κ³± κ°’ + +## μƒˆλ‘œμš΄ κ°’ num이 μ£Όμ–΄μ‘Œμ„ λ•Œ +- μƒˆλ‘œμš΄ 배열을 μ‹œμž‘ν•  μ§€, κΈ°μ‘΄ 배열에 μΆ”κ°€ν•  μ§€ κ²°μ • +- ν›„λ³΄λ“€λ‘œ μ΅œλŒ€κ°’μ˜ κ°€λŠ₯성을 ν™•μΈν•˜κ³  resultλ₯Ό μ—…λ°μ΄νŠΈν•œλ‹€. +''' +class Solution: + def maxProduct(self, nums: List[int]) -> int: + result = nums[0] + min_prod = 1 + max_prod = 1 + + for num in nums: + candidates = (min_prod * num, max_prod * num, num) + min_prod = min(candidates) + max_prod = max(candidates) + result = max(max_prod, result) + + return result \ No newline at end of file From 52cb217c2f7570860d226db7e79c6d1856ec1060 Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Sat, 8 Feb 2025 22:18:46 +0900 Subject: [PATCH 7/8] fix: add new line --- maximum-product-subarray/dusunax.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maximum-product-subarray/dusunax.py b/maximum-product-subarray/dusunax.py index b8c3dcd74..e2f796ce8 100644 --- a/maximum-product-subarray/dusunax.py +++ b/maximum-product-subarray/dusunax.py @@ -28,4 +28,4 @@ def maxProduct(self, nums: List[int]) -> int: max_prod = max(candidates) result = max(max_prod, result) - return result \ No newline at end of file + return result From 7a9c45abf41a74c0e85557c87e0bdd13725bde8e Mon Sep 17 00:00:00 2001 From: Dusuna <94776135+dusunax@users.noreply.github.com> Date: Sun, 9 Feb 2025 00:12:30 +0900 Subject: [PATCH 8/8] add solution: minimum-window-substring --- minimum-window-substring/dusunax.py | 68 +++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 minimum-window-substring/dusunax.py diff --git a/minimum-window-substring/dusunax.py b/minimum-window-substring/dusunax.py new file mode 100644 index 000000000..b8d6fe66c --- /dev/null +++ b/minimum-window-substring/dusunax.py @@ -0,0 +1,68 @@ +''' +# 76. Minimum Window Substring + +solution reference: https://www.algodale.com/problems/minimum-window-substring/ + +## μ£Όμ–΄μ§„ λ¬Έμžμ—΄ sμ—μ„œ λ¬Έμžμ—΄ t의 λͺ¨λ“  문자λ₯Ό ν¬ν•¨ν•˜λŠ” μ΅œμ†Œ μœˆλ„μš°λ₯Ό μ°Ύμ•„ λ°˜ν™˜ν•˜κΈ° πŸ”₯ + +> μŠ¬λΌμ΄λ”© μœˆλ„μš°, μ΅œμ†Œ μœˆλ„μš° μ°ΎκΈ°, λ¬Έμžμ—΄μ˜ λΉˆλ„ 좔적, t의 λͺ¨λ“  λ¬Έμžκ°€ ν˜„μž¬ μœˆλ„μš°μ— ν¬ν•¨λ˜μ–΄ μžˆλŠ”μ§€ 좔적 + +- μœˆλ„μš°μ˜ 였λ₯Έμͺ½ 끝을 ν™•μž₯ν•˜λ©΄μ„œ, ν•„μš”ν•œ λͺ¨λ“  λ¬Έμžκ°€ ν¬ν•¨λ˜μ—ˆμ„ λ•Œ, μœˆλ„μš°μ˜ 크기λ₯Ό μ΅œμ†Œν™”ν•˜κΈ° + +## κ°’ +- counts: ν•„μš”ν•œ λ¬Έμžκ°€ λͺ‡ 번 λ“±μž₯ν•˜λŠ”μ§€ 좔적 +- n_included: μœˆλ„μš° μ•ˆμ—μ„œ t에 ν•„μš”ν•œ 문자 개수 좔적 +- low, high: μŠ¬λΌμ΄λ”© μœˆλ„μš°μ˜ μ–‘ 끝 +- min_low max_high: λ°˜ν™˜κ°’, μŠ¬λΌμ΄λ”© μœˆλ„μš°μ˜ μ–‘ 끝 + +## s 탐색 +- s의 였λ₯Έμͺ½ 끝을 νƒμƒ‰ν•©λ‹ˆλ‹€. + - ν˜„μž¬ λ¬Έμžκ°€ t에 μ‘΄μž¬ν•œλ‹€λ©΄(counts에 ν‚€κ°€ 쑴재) + - 그리고 ν•„μš”ν•œ 문자라면(값이 1 이상) + - μœˆλ„μš° λ‚΄λΆ€μ˜ ν•„μš” 문자 개수λ₯Ό ν•˜λ‚˜ μ¦κ°€μ‹œν‚΅λ‹ˆλ‹€. + - ν•΄λ‹Ή 문자의 λ“±μž₯ countλ₯Ό ν•˜λ‚˜ κ°μ†Œμ‹œν‚΅λ‹ˆλ‹€. + +## μœˆλ„μš° μΆ•μ†Œν•˜κΈ° +- μ•„λž˜ 문항을 ν•„μš”ν•œ 값이 μœˆλ„μš° μ•ˆμ— μ‘΄μž¬ν•˜λŠ” λ™μ•ˆ λ°˜λ³΅ν•©λ‹ˆλ‹€. +1. ν˜„μž¬ κ΅¬ν•œ μœˆλ„μš°κ°€ 더 μž‘μ€ μ§€ ν™•μΈν•˜κ³ , μž‘λ‹€λ©΄ λ°˜ν™˜ν•  μœˆλ„μš°λ₯Ό μ—…λ°μ΄νŠΈ ν•©λ‹ˆλ‹€. +2. s의 μ™Όμͺ½ 끝을 νƒμƒ‰ν•©λ‹ˆλ‹€. + - ν˜„μž¬ λ¬Έμžκ°€ t에 μ‘΄μž¬ν•œλ‹€λ©΄(counts에 ν‚€κ°€ 쑴재) + - ν•΄λ‹Ή 문자의 λ“±μž₯ countλ₯Ό ν•˜λ‚˜ μ¦κ°€μ‹œν‚΅λ‹ˆλ‹€. + - 그리고 ν•„μš”ν•œ 문자라면(값이 1 이상) + - μœˆλ„μš° λ‚΄λΆ€μ˜ ν•„μš” 문자 개수λ₯Ό ν•˜λ‚˜ μΆ•μ†Œμ‹œν‚΅λ‹ˆλ‹€.(반볡문의 쑰건을 λ²—μ–΄λ‚©λ‹ˆλ‹€.) +3. λ‹€μŒ 탐색 μ „ μ™Όμͺ½ μœ„μΉ˜λ₯Ό ν•˜λ‚˜ μ¦κ°€μ‹œν‚΅λ‹ˆλ‹€. + +## λ°˜ν™˜ +- μ΅œμ†Œ μœˆλ„μš°μ˜ μ‹œμž‘κ³Ό 끝을 low와 high + 1둜 λ°˜ν™˜ν•˜λ˜, μœ νš¨ν•œ μœˆλ„μš°κ°€ μ•„λ‹ˆλΌλ©΄ ""을 λ°˜ν™˜ν•©λ‹ˆλ‹€. +''' +class Solution: + def minWindow(self, s: str, t: str) -> str: + min_low = 0 + max_high = len(s) + counts = Counter(t) + n_included = 0 + + low = 0 + # s 탐색 + for high in range(len(s)): + char_high = s[high] + if char_high in counts: + if counts[char_high] > 0: + n_included += 1 + counts[char_high] -= 1 + + # μœˆλ„μš° μΆ•μ†Œν•˜κΈ° + while n_included == len(t): + if high - low < max_high - min_low: # 1 + min_low = low + max_high = high + + char_low = s[low] + if char_low in counts: # 2 + counts[char_low] += 1 + if counts[char_low] > 0: + n_included -= 1 + + low += 1 # 3 + + return s[min_low: max_high + 1] if max_high < len(s) else ""