Skip to content

[KwonNayeon] Week 14 Solutions #1637

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 4 commits into from
Jul 6, 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
53 changes: 53 additions & 0 deletions find-median-from-data-stream/KwonNayeon.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.

<Solution 1: 리스트 활용>

Time Complexity:
- addNum(): O(nlogn)
- 매번 정렬하기 때문
Expand Down Expand Up @@ -41,3 +43,54 @@ def findMedian(self) -> float:
mid2 = self.nums[n // 2]
return (mid1 + mid2) / 2.0

"""
<Solution 2: 힙 활용>

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
70 changes: 70 additions & 0 deletions word-search-ii/KwonNayeon.py
Original file line number Diff line number Diff line change
@@ -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
22 changes: 10 additions & 12 deletions word-search/KwonNayeon.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,39 @@
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:
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):
Expand Down