diff --git a/find-median-from-data-stream/KwonNayeon.py b/find-median-from-data-stream/KwonNayeon.py index bd2146bcb..90aa9b643 100644 --- a/find-median-from-data-stream/KwonNayeon.py +++ b/find-median-from-data-stream/KwonNayeon.py @@ -4,6 +4,8 @@ - There will be at least one element in the data structure before calling findMedian. - At most 5 * 10^4 calls will be made to addNum and findMedian. + + Time Complexity: - addNum(): O(nlogn) - 매번 정렬하기 때문 @@ -41,3 +43,54 @@ def findMedian(self) -> float: mid2 = self.nums[n // 2] return (mid1 + mid2) / 2.0 +""" + + +Time Complexity: +- addNum(): O(log n) - 힙에 삽입/삭제 연산 +- findMedian(): O(1) - 힙의 루트 요소만 접근 + +Space Complexity: +- O(n) - 모든 입력 숫자를 두 개의 힙에 저장 + +풀이방법: +max/min heap을 사용해서 데이터를 절반씩 나누어 median 값을 찾음 +1. 자료구조 + - lower (max heap) + - upper (min heap) +2. addNum + - upper가 비어있거나 새로운 숫자가 upper[0]보다 크면 upper에 추가 + - 그렇지 않으면 lower에 추가 +3. 균형 유지 + - 두 힙의 크기 차이가 최대 1이 되도록 조정함 + - lower가 더 많으면 upper로 이동 + - upper가 2개 이상 더 많으면 lower로 이동 +4. 중간값 계산 + - 홀수개: upper[0] (upper가 항상 1개 더 많거나 같기 때문) + - 짝수개: (-lower[0] + upper[0]) / 2 +""" +from heapq import heappop, heappush + +class MedianFinder: + + def __init__(self): + self.lower = [] + self.upper = [] + + def addNum(self, num: int) -> None: + if not self.upper or self.upper[0] < num: + heappush(self.upper, num) + else: + heappush(self.lower, -num) + + if len(self.lower) > len(self.upper): + heappush(self.upper, -heappop(self.lower)) + elif len(self.lower) + 1 < len(self.upper): + heappush(self.lower, -heappop(self.upper)) + + def findMedian(self) -> float: + if len(self.lower) < len(self.upper): + return self.upper[0] + + else: + return (-self.lower[0] + self.upper[0]) / 2 diff --git a/word-search-ii/KwonNayeon.py b/word-search-ii/KwonNayeon.py new file mode 100644 index 000000000..407b82fcd --- /dev/null +++ b/word-search-ii/KwonNayeon.py @@ -0,0 +1,70 @@ +""" +Constraints: +- m == board.length +- n == board[i].length +- 1 <= m, n <= 12 +- board[i][j] is a lowercase English letter. +- 1 <= words.length <= 3 * 10^4 +- 1 <= words[i].length <= 10 +- words[i] consists of lowercase English letters. +- All the strings of words are unique. + +Time Complexity: O(W * N * 4^L) +- W는 words의 개수 +- N은 board의 모든 cell (m * n) +- L은 word의 길이 +- 각 단어마다 Word Search 1을 반복 + +Space Complexity: O(L) +- L은 word의 길이로, 재귀 호출 스택의 깊이 + +Word search 1과의 차이점: +- 단어 여러개를 동시에 찾아야 함 +- 찾은 모든 단어들을 리스트로 반환해야 함 + +풀이방법: +- Word search 1과 동일한 방법 + set(words)로 중복 제거 + +노트: +- 시간초과로 통과 안 됨 +- Trie 자료구조로 다시 풀어보기 +""" +class Solution: + def findWords(self, board: List[List[str]], words: List[str]) -> List[str]: + words = list(set(words)) + result = [] + + def exist(word): + rows, cols = len(board), len(board[0]) + + def dfs(i, j, k): + if k == len(word): + return True + + if (i < 0 or i >= rows or + j < 0 or j >= cols or + board[i][j] != word[k]): + return False + + temp = board[i][j] + board[i][j] = '#' + + result = (dfs(i+1, j, k+1) or + dfs(i-1, j, k+1) or + dfs(i, j+1, k+1) or + dfs(i, j-1, k+1)) + + board[i][j] = temp + return result + + for i in range(rows): + for j in range(cols): + if board[i][j] == word[0]: + if dfs(i, j, 0): + return True + return False + + for word in words: + if exist(word): + result.append(word) + return result diff --git a/word-search/KwonNayeon.py b/word-search/KwonNayeon.py index 39cc5fd2e..ad8db4be6 100644 --- a/word-search/KwonNayeon.py +++ b/word-search/KwonNayeon.py @@ -6,17 +6,13 @@ 4. word length is between 1 and 15 inclusive 5. board and word contain only lowercase and uppercase English letters -Time Complexity: O(N * 3^L) +Time Complexity: O(N * 4^L) - N은 board의 모든 cell (m * n) - L은 word의 길이 - - 각 cell에서 시작하여 word의 각 글자마다 세방향으로 탐색 (이미 방문한 방향 제외) + - 각 cell에서 시작하여 word의 각 글자마다 네방향으로 탐색 (이미 방문한 방향 제외) Space Complexity: O(L) - L은 word의 길이로, 재귀 호출 스택의 깊이 - -To Do: - - DFS와 백트래킹 개념 복습하기 - - 다른 스터디원분들의 답안 참조하여 다른 풀이방법 복습하기 """ class Solution: @@ -24,23 +20,25 @@ def exist(self, board: List[List[str]], word: str) -> bool: rows, cols = len(board), len(board[0]) def dfs(i, j, k): + + # 단어를 모두 찾았으면 True 반환 if k == len(word): return True - if (i < 0 or i >= rows or + if (i < 0 or i >= rows or # 경계체크 j < 0 or j >= cols or - board[i][j] != word[k]): + board[i][j] != word[k]): # 현재 문자가 찾는 문자와 다름 return False - temp = board[i][j] - board[i][j] = '#' + temp = board[i][j] # 현재 문자를 임시저장 + board[i][j] = '#' # 방문 표시 - result = (dfs(i+1, j, k+1) or + result = (dfs(i+1, j, k+1) or # 상하좌우 네 방향 탐색 dfs(i-1, j, k+1) or dfs(i, j+1, k+1) or dfs(i, j-1, k+1)) - board[i][j] = temp + board[i][j] = temp # 백트래킹 (원래 문자로 복원) return result for i in range(rows):