Skip to content

[suwi] Week 09 #1003

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions find-minimum-in-rotated-sorted-array/sungjinwi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
"""
풀이 :
최초 시작 시 nums[left]가 nums[right]보다 작은 경우는 n만큼 rotate된 상태(원래 자신)
같은 경우는 len(nums) == 1인 경우
mid와 right의 값을 비교해서 mid의 값이 작다면 mid부터 right까지는 정렬되있으므로 좌측에 최솟값 존재
-> right = mid - 1
반대의 경우는 최솟값이 우측에 있으므로 left = mid + 1

- left, mid, right을 적절히 할당할 수 있도록 수식 구현 잘할 것
- mid가 최솟값일 경우에 대한 예외처리

nums의 길이 : n

TC : O(logN)
반씩 나눠서 탐색하므로 log2N

SC : O(1)
"""

class Solution:
def findMin(self, nums: List[int]) -> int:
left = 0
right = len(nums) - 1
if nums[left] <= nums[right] :
return nums[left]
while (nums[right] < nums[left]):
mid = (left + right) // 2
if nums[mid - 1] > nums[mid]:
return nums[mid]
if nums[mid] < nums[right] :
right = mid - 1
else :
left = mid + 1
return nums[left]
29 changes: 29 additions & 0 deletions linked-list-cycle/sungjinwi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""
풀이 :
set에 지나온 node를 저장하고 새 node로 이동하면 set안에 존재하는지 확인
이미 존재하는 node를 지나면 True
None에 도달하면 False

노드의 길이 = n

TC : O(N)

SC : O(N)
"""

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None

class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
visited = set()
while head :
if head in visited :
return True
else :
visited.add(head)
head = head.next
return False
52 changes: 32 additions & 20 deletions maximum-product-subarray/sungjinwi.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
"""
/풀이 봐도 잘 이해 못해서 추가 코멘트/
nums[i]가 그 전까지 subarray의 합 total보다 작은 음수인 케이스는 어떻게 되는거지 고민했는데
ex) total : -1, nums[i] = -2
어차피 -1인 시점에 maxTotal이 업데이트 됐으므로 total은 nums[i]부터 더하기 시작한다는 의미로 -2로 설정한다는 것을 깨달음
따라서 이전까지 subarray의 합만 음수 양수 체크

TC : for문 한번
=> O(N)
SC : 추가적인 배열 등 메모리 쓰지 않으므로
=> O(1)
** 실수로 예전 과제 수행 때 다른 과제폴더에 파일을 만들어서 파일 수정합니다!!

풀이 :
nums의 구성요소 num에 따라 각각 후보1, 후보2, 후보3 중에
가장 큰 값은 새로운 max_res, 가장 작은 값은 새로운 min_res

후보1: 이전 max_res * 현재 num (num이 양수일 경우 가장 클 가능성)
후보2: 이전 min_res * 현재 num (num이 음수일 경우 가장 클 가능성)
후보3: 현재 num (num이 양수일 경우 가장 클 가능성)

새로운 max_res와 max_total을 비교해서 업데이트


메모 :
- 현재 num이 0일 경우 후보 셋 모두 0
- 음수 양수 0 등으로 조건을 나누지 않고 min과 max로만 구분해도 충분하다
- max_res와 min_res는 곱해지므로 초기화를 1로 한다 (또는 반복문을 인덱스로 반복하고 1부터 시작)


nums의 길이 : n

TC : O(N)

SC : O(1)
"""

class Solution:
def maxSubArray(self, nums: List[int]) -> int:
total = nums[0]
maxTotal = nums[0]
for i in range(1, len(nums)) :
if (total < 0) :
total = nums[i]
else :
total += nums[i]
maxTotal = max(total, maxTotal)
return (maxTotal)
def maxProduct(self, nums: List[int]) -> int:
max_total, max_res, min_res = nums[0], 1, 1
for num in nums :
min_res, max_res = min(num, max_res * num, min_res * num), \
max(num, max_res * num, min_res * num)
max_total = max(max_total, max_res)
return max_total
23 changes: 23 additions & 0 deletions maximum-subarray/sungjinwi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
"""
/풀이 봐도 잘 이해 못해서 추가 코멘트/
nums[i]가 그 전까지 subarray의 합 total보다 작은 음수인 케이스는 어떻게 되는거지 고민했는데
ex) total : -1, nums[i] = -2
어차피 -1인 시점에 maxTotal이 업데이트 됐으므로 total은 nums[i]부터 더하기 시작한다는 의미로 -2로 설정한다는 것을 깨달음
따라서 이전까지 subarray의 합만 음수 양수 체크

TC : for문 한번
=> O(N)
SC : 추가적인 배열 등 메모리 쓰지 않으므로
=> O(1)
"""
class Solution:
def maxSubArray(self, nums: List[int]) -> int:
total = nums[0]
maxTotal = nums[0]
for i in range(1, len(nums)) :
if (total < 0) :
total = nums[i]
else :
total += nums[i]
maxTotal = max(total, maxTotal)
return (maxTotal)
38 changes: 38 additions & 0 deletions minimum-window-substring/sungjinwi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""
풀이 : 슬라이딩 윈도우 이용
딕셔너리를 이용해 문자의 등장 빈도를 확인, 증가, 감소시킨다
t에 존재하는 모든 문자의 빈도보다 s의 빈도가 같거나 커질 때까지 right를 증가시킨다
left를 증가시키며 s[left]의 문자빈도가 t보다 낮아지는 지점을 찾는다
기존의 min_total길이보다 짧으면 ans에 left, right 정보를 이용해 update

알고달레 참조 및 좀 더 최적화 필요

s의 길이 : n

"""

class Solution:
def minWindow(self, s: str, t: str) -> str:
left, right = 0, 0
min_total = len(s)
s_appear = {}
t_appear = {}
ans = ""
for char in set(t):
s_appear[char] = 0
t_appear[char] = t.count(char)
while (right < len(s)):
if s[right] in s_appear:
s_appear[s[right]] += 1
if all(s_appear[char] >= t_appear[char] for char in t_appear.keys()):
while left < right:
if s[left] in s_appear:
if s_appear[s[left]] == t_appear[s[left]]:
break
s_appear[s[left]] -= 1
left += 1
if (right - left + 1) < min_total:
min_total = right - left + 2
ans = s[left:right + 1]
right += 1
return ans
44 changes: 44 additions & 0 deletions pacific-atlantic-water-flow/sungjinwi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""
풀이 :
빗물이 흘러가서 바다에 도착하는 경우가 아닌 역으로 바다에서 출발해서 도달할 수 있는 경우를 찾는다
4방향 중에 height가 현재 위치보다 높거나 같으면 위로 흘러갈 수 있고 visited set에 저장해서
이미 도달한 곳은 return 으로 처리한다
바다와 위아래로 맞닿은 해안과 좌우로 맞닿은 해안에서 각각 출발하도록 두번의 반복문을 수행

r, c : 행렬의 길이

TC : O(R * C)
visited_set을 통해 pacific, atlantic이 최악의 경우에도 섬 전체를 한번씩 순회하므로

SC : O(R * C)
각 set의 크기와 dfs 호출 스택은 섬 크기에 비례하므로
"""

class Solution:
def pacificAtlantic(self, heights: List[List[int]]) -> List[List[int]]:
paci_visited, atl_visited = set(), set()
n_rows = len(heights)
n_cols = len(heights[0])

def dfs(r: int, c: int, visited: set) -> None:
if (r, c) in visited:
return
visited.add((r, c))
for (m, n) in [(r + 1, c), (r - 1, c), (r, c + 1), (r, c - 1)]:
if 0 <= m < n_rows and 0 <= n < n_cols:
if heights[r][c] <= heights[m][n]:
dfs(m, n, visited)

for r in range(n_rows):
dfs(r, 0, paci_visited)
dfs(r, n_cols - 1, atl_visited)

for c in range(n_cols):
dfs(0, c, paci_visited)
dfs(n_rows - 1, c, atl_visited)

result = []
for both in paci_visited.intersection(atl_visited):
result.append(list(both))

return result