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 ""