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