Skip to content

Commit 22ede51

Browse files
authored
Merge pull request #991 from dusunax/main
[SunaDu] Week 9
2 parents 113af65 + 7a9c45a commit 22ede51

File tree

5 files changed

+215
-0
lines changed

5 files changed

+215
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
'''
2+
# 153. Find Minimum in Rotated Sorted Array
3+
4+
> **why binary search works in a "rotated" sorted array?**
5+
> rotated sorted array consists of **two sorted subarrays**, and the minimum value is the second sorted subarray's first element.
6+
> so 👉 find the point that second sorted subarray starts.
7+
>
8+
> - if nums[mid] > nums[right]? => the pivot point is in the right half.
9+
> - if nums[mid] <= nums[right]? => the pivot point is in the left half.
10+
> - loop until left and right are the same.
11+
'''
12+
class Solution:
13+
'''
14+
## A. brute force(not a solution)
15+
- TC: O(n)
16+
- SC: O(1)
17+
'''
18+
def findMinBF(self, nums: List[int]) -> int:
19+
if len(nums) == 1:
20+
return nums[0]
21+
22+
return min(nums) # check all elements
23+
24+
'''
25+
## B. binary search
26+
- TC: O(log n)
27+
- SC: O(1)
28+
'''
29+
def findMinBS(self, nums: List[int]) -> int:
30+
left = 0
31+
right = len(nums) - 1
32+
33+
while left < right:
34+
mid = (left + right) // 2
35+
36+
if nums[mid] > nums[right]:
37+
left = mid + 1
38+
else:
39+
right = mid
40+
41+
return nums[left]

linked-list-cycle/dusunax.py

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'''
2+
# 141. Linked List Cycle
3+
4+
use two pointers, Floyd's Tortoise and Hare algorithm
5+
6+
> Tortoise and Hare algorithm
7+
>- slow pointer moves one step at a time
8+
>- fast pointer moves two steps at a time
9+
>- if there is a cycle, slow and fast will meet at some point
10+
>- if there is no cycle, fast will reach the end of the list
11+
12+
## Time Complexity: O(n)
13+
In the worst case, we need to traverse the entire list to determine if there is a cycle.
14+
15+
## Space Complexity: O(1)
16+
no extra space is used, only the two pointers.
17+
'''
18+
class Solution:
19+
def hasCycle(self, head: Optional[ListNode]) -> bool:
20+
if not head or not head.next:
21+
return False
22+
23+
slow = head
24+
fast = head
25+
26+
while fast and fast.next:
27+
slow = slow.next
28+
fast = fast.next.next
29+
30+
if slow == fast:
31+
return True
32+
33+
return False

maximum-product-subarray/dusunax.py

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'''
2+
# 152. Maximum Product Subarray
3+
4+
solution reference: https://www.algodale.com/problems/maximum-product-subarray/
5+
6+
## 최대 곱 배열 구하기
7+
- 연속 배열(subarray)에 양수, 음수, 0이 포함될 수 있다.
8+
- 음수가 결과에 영향을 미칠 수 있기 때문에 최소값/최대값 추적이 필요하다.
9+
10+
## 값
11+
- result: 최종적으로 반환할 값
12+
- min_prod: 현재까지의 최소 곱 값 (음수를 고려한 추적)
13+
- max_prod: 현재까지의 최대 곱 값
14+
15+
## 새로운 값 num이 주어졌을 때
16+
- 새로운 배열을 시작할 지, 기존 배열에 추가할 지 결정
17+
- 후보들로 최대값의 가능성을 확인하고 result를 업데이트한다.
18+
'''
19+
class Solution:
20+
def maxProduct(self, nums: List[int]) -> int:
21+
result = nums[0]
22+
min_prod = 1
23+
max_prod = 1
24+
25+
for num in nums:
26+
candidates = (min_prod * num, max_prod * num, num)
27+
min_prod = min(candidates)
28+
max_prod = max(candidates)
29+
result = max(max_prod, result)
30+
31+
return result

minimum-window-substring/dusunax.py

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
'''
2+
# 76. Minimum Window Substring
3+
4+
solution reference: https://www.algodale.com/problems/minimum-window-substring/
5+
6+
## 주어진 문자열 s에서 문자열 t의 모든 문자를 포함하는 최소 윈도우를 찾아 반환하기 🔥
7+
8+
> 슬라이딩 윈도우, 최소 윈도우 찾기, 문자열의 빈도 추적, t의 모든 문자가 현재 윈도우에 포함되어 있는지 추적
9+
10+
- 윈도우의 오른쪽 끝을 확장하면서, 필요한 모든 문자가 포함되었을 때, 윈도우의 크기를 최소화하기
11+
12+
## 값
13+
- counts: 필요한 문자가 몇 번 등장하는지 추적
14+
- n_included: 윈도우 안에서 t에 필요한 문자 개수 추적
15+
- low, high: 슬라이딩 윈도우의 양 끝
16+
- min_low max_high: 반환값, 슬라이딩 윈도우의 양 끝
17+
18+
## s 탐색
19+
- s의 오른쪽 끝을 탐색합니다.
20+
- 현재 문자가 t에 존재한다면(counts에 키가 존재)
21+
- 그리고 필요한 문자라면(값이 1 이상)
22+
- 윈도우 내부의 필요 문자 개수를 하나 증가시킵니다.
23+
- 해당 문자의 등장 count를 하나 감소시킵니다.
24+
25+
## 윈도우 축소하기
26+
- 아래 문항을 필요한 값이 윈도우 안에 존재하는 동안 반복합니다.
27+
1. 현재 구한 윈도우가 더 작은 지 확인하고, 작다면 반환할 윈도우를 업데이트 합니다.
28+
2. s의 왼쪽 끝을 탐색합니다.
29+
- 현재 문자가 t에 존재한다면(counts에 키가 존재)
30+
- 해당 문자의 등장 count를 하나 증가시킵니다.
31+
- 그리고 필요한 문자라면(값이 1 이상)
32+
- 윈도우 내부의 필요 문자 개수를 하나 축소시킵니다.(반복문의 조건을 벗어납니다.)
33+
3. 다음 탐색 전 왼쪽 위치를 하나 증가시킵니다.
34+
35+
## 반환
36+
- 최소 윈도우의 시작과 끝을 low와 high + 1로 반환하되, 유효한 윈도우가 아니라면 ""을 반환합니다.
37+
'''
38+
class Solution:
39+
def minWindow(self, s: str, t: str) -> str:
40+
min_low = 0
41+
max_high = len(s)
42+
counts = Counter(t)
43+
n_included = 0
44+
45+
low = 0
46+
# s 탐색
47+
for high in range(len(s)):
48+
char_high = s[high]
49+
if char_high in counts:
50+
if counts[char_high] > 0:
51+
n_included += 1
52+
counts[char_high] -= 1
53+
54+
# 윈도우 축소하기
55+
while n_included == len(t):
56+
if high - low < max_high - min_low: # 1
57+
min_low = low
58+
max_high = high
59+
60+
char_low = s[low]
61+
if char_low in counts: # 2
62+
counts[char_low] += 1
63+
if counts[char_low] > 0:
64+
n_included -= 1
65+
66+
low += 1 # 3
67+
68+
return s[min_low: max_high + 1] if max_high < len(s) else ""
+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'''
2+
# 417. Pacific Atlantic Water Flow
3+
4+
## Time Complexity: O(n * m)
5+
- dfs is called for each cell in the grid, and each cell is visited once.
6+
7+
## Space Complexity: O(n * m)
8+
- pacific and atlantic sets store the cells that can flow to the pacific and atlantic oceans respectively.
9+
'''
10+
class Solution:
11+
def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]:
12+
if len(heights) == 1 and len(heights[0]) == 1:
13+
return [[0, 0]]
14+
15+
max_row, max_col = len(heights), len(heights[0])
16+
pacific, atlantic = set(), set()
17+
directions = [(1, 0), (0, 1), (-1, 0), (0, -1)]
18+
19+
def dfs(r, c, visited, prev_height):
20+
out_of_bound = r < 0 or c < 0 or r >= max_row or c >= max_col
21+
if out_of_bound:
22+
return
23+
24+
current = heights[r][c]
25+
is_visited = (r, c) in visited
26+
is_uphill = current < prev_height
27+
if is_visited or is_uphill:
28+
return
29+
30+
visited.add((r, c))
31+
32+
for dr, dc in directions:
33+
dfs(r + dr, c + dc, visited, current)
34+
35+
for r in range(max_row):
36+
dfs(r, 0, pacific, heights[r][0]) # left
37+
dfs(r, max_col - 1, atlantic, heights[r][max_col - 1]) # right
38+
for c in range(max_col):
39+
dfs(0, c, pacific, heights[0][c]) # top
40+
dfs(max_row - 1, c, atlantic, heights[max_row - 1][c]) # bottom
41+
42+
return list(pacific & atlantic)

0 commit comments

Comments
 (0)