Skip to content

[river20s] WEEK 08 solutions #1507

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
49 changes: 49 additions & 0 deletions clone-graph/river20s.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""
# Definition for a Node.
class Node:
def __init__(self, val = 0, neighbors = None):
self.val = val
self.neighbors = neighbors if neighbors is not None else []
"""

from typing import Optional
class Solution:
def cloneGraph(self, node: Optional['Node']) -> Optional['Node']:
"""
Time Complexity: O(n + m) (n은 노드의 개수, m은 간선 개수)
Space Complexity: O(n) (노드 개수만큼 맵 사용)
"""
# clones_map 딕셔너리
# key: 원본 노드 객체
# value: 복제 노드 객체
clones_map = {} # 노드를 복제 하고 바로 등록할 딕셔너리

def dfs_clone(original_node: Optional['Node']) -> Optional['Node']:
# 원본 노드가 비어있으면 None 반환
if not original_node:
return None

# 원본 노드가 clones_map에 있다면
# 전에 복제 했음을 의미, 해당 복제 노드 객체를 반환
if original_node in clones_map:
return clones_map[original_node]

# 새로운 복제 노드 생성 후 val 복사
new_clone = Node(original_node.val)
# 위에서 생성된 복제 노드를 clones_map에 등록
clones_map[original_node] = new_clone

# 원본 노드의 이웃을 복사
if original_node.neighbors:
# 각각의 이웃 노드들에 대해 처리
for original_neighbor in original_node.neighbors:
# 재귀적으로 dfs_clone 호출하여 clone
# (위 작업에 의해 이미 복제 했다면, 복제된 객체가 반환 될 것)
cloned_neighbor = dfs_clone(original_neighbor)
# 새로 복제된 노드 new_clone의 이웃으로 추가
new_clone.neighbors.append(cloned_neighbor)

return new_clone # 완성된 복제 노드 반환

# 시작 노드로부터 재귀적인 복제 시작
return dfs_clone(node)
41 changes: 41 additions & 0 deletions longest-repeating-character-replacement/river20s.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
class Solution:
def characterReplacement(self, s: str, k: int) -> int:
"""
Time Complexity: O(n)
Space Complexity: O(1)
"""
n = len(s)

if n == 0:
return 0

left = 0 # 윈도우의 왼쪽 인덱스 (시작)
max_len = 0 # 가장 긴 유효한 부분 문자열 길이
char_counts = {} # 현 윈도우 안에서 각 문자 빈도수
max_freq_count = 0 # 현 윈도우 안에서 가장 많이 등장한 문자 빈도수

for right in range(n):
right_char = s[right] # 윈도우 오른쪽에 추가할 문자

# 추가할 문자 빈도수 갱신
char_counts[right_char] = char_counts.get(right_char, 0) + 1

max_freq_count = max(max_freq_count, char_counts[right_char])

current_window_length = right - left + 1

# 바꿔야 하는 문자 수 = 윈도우 길이 - 가장 많은 문자의 빈도수
changes_needed = current_window_length - max_freq_count

# 만약 바꿔야 하는 문자 수가 k보다 크면
# 유효하지 않은 윈도우 => 윈도우를 줄여야 함
if changes_needed > k:
left_char = s[left] # 제거할 문자
char_counts[left_char] -= 1 # 빈도수 줄이기

left += 1 # 윈도우 축소

# 최대 길이 업데이트, 반환
max_len = max(max_len, right - left + 1)

return max_len
59 changes: 59 additions & 0 deletions reverse-bits/river20s.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
class Solution:
# -- follow up
# If this function is called many times,
# how would you optimize it?
# - 클래스 변수로 lookup table 만들어
# - 8bits 단위로 미리 비트 뒤집은 테이블을 만들어두는 방법
# _lookup_table_8bit = [0] * 256
# for i in range(256):
# val = i
# rev_val = 0
# for _ in range(8): # 8비트 뒤집기
# rev_val = (rev_val << 1) | (val & 1)
# val >>= 1
# _lookup_table_8bit[i] = rev_val
# def __init__(self):
# pass

def reverseBits(self, n: int) -> int:
"""
Time Complexity: O(1)
Space Complexity: O(1)
- 항상 32번 연산하므로 O(1),
- 함수가 여러 번 호출되면 누적되어 성능 영향 줄 수도 있음
-> reverseBits_lookupTable() 사용
"""
reversed_n = 0 # 뒤집은 비트 저장
num_bits = 32

for i in range(num_bits):
reversed_n <<= 1

if (n & 1) == 1:
reversed_n |= 1

n >>= 1

return reversed_n

def reverseBits_lookupTable(self, n: int) -> int:
"""
Time Complexity: O(1)
Space Complexity: O(1)
- 룩업 테이블 생성 시 공간 필요
- 하지만 최초 한 번만 필요하므로
- 호출 누적되면 연산량은 더 적음
"""
b0 = (n >> 0) & 0xFF
b1 = (n >> 8) & 0xFF
b2 = (n >> 16) & 0xFF
b3 = (n >> 24) & 0xFF

rev_b0 = self._lookup_table_8bit[b0]
rev_b1 = self._lookup_table_8bit[b1]
rev_b2 = self._lookup_table_8bit[b2]
rev_b3 = self._lookup_table_8bit[b3]

result = (rev_b0 << 24) | (rev_b1 << 16) | (rev_b2 << 8) | rev_b3

return result