diff --git a/find-minimum-in-rotated-sorted-array/sungjinwi.py b/find-minimum-in-rotated-sorted-array/sungjinwi.py new file mode 100644 index 000000000..0846769ae --- /dev/null +++ b/find-minimum-in-rotated-sorted-array/sungjinwi.py @@ -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] diff --git a/linked-list-cycle/sungjinwi.py b/linked-list-cycle/sungjinwi.py new file mode 100644 index 000000000..18d000665 --- /dev/null +++ b/linked-list-cycle/sungjinwi.py @@ -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 diff --git a/maximum-product-subarray/sungjinwi.py b/maximum-product-subarray/sungjinwi.py index e8f82028d..965a43763 100644 --- a/maximum-product-subarray/sungjinwi.py +++ b/maximum-product-subarray/sungjinwi.py @@ -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 diff --git a/maximum-subarray/sungjinwi.py b/maximum-subarray/sungjinwi.py new file mode 100644 index 000000000..e8f82028d --- /dev/null +++ b/maximum-subarray/sungjinwi.py @@ -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) diff --git a/minimum-window-substring/sungjinwi.py b/minimum-window-substring/sungjinwi.py new file mode 100644 index 000000000..73cabaa34 --- /dev/null +++ b/minimum-window-substring/sungjinwi.py @@ -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 diff --git a/pacific-atlantic-water-flow/sungjinwi.py b/pacific-atlantic-water-flow/sungjinwi.py new file mode 100644 index 000000000..c07cca35f --- /dev/null +++ b/pacific-atlantic-water-flow/sungjinwi.py @@ -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