diff --git a/clone-graph/pmjuu.py b/clone-graph/pmjuu.py new file mode 100644 index 000000000..b3f58cc82 --- /dev/null +++ b/clone-graph/pmjuu.py @@ -0,0 +1,40 @@ +''' +시간 복잡도: O(V + E) +- 그래프의 모든 노드를 한 번씩 방문해야 하므로 O(V) +- 각 노드의 모든 간선을 한 번씩 탐색해야 하므로 O(E) +- 따라서 전체 시간 복잡도는 O(V + E) + +공간 복잡도: O(V + E) +- 클론 노드를 저장하는 딕셔너리(clones): O(V) +- BFS 탐색을 위한 큐(queue): O(V) +- 복제된 그래프의 노드와 간선 저장 공간: O(V + E) +''' + +from typing import Optional +from collections import deque +# 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 [] + +class Solution: + def cloneGraph(self, node: Optional['Node']) -> Optional['Node']: + if not node: + return None + + clones = { node.val: Node(node.val) } + queue = deque([node]) + + while queue: + current_node = queue.popleft() + + for neighbor in current_node.neighbors: + # add neighbors + if neighbor.val not in clones.keys(): + queue.append(neighbor) + clones[neighbor.val] = Node(neighbor.val) + + clones[current_node.val].neighbors.append(clones[neighbor.val]) + + return clones[node.val] diff --git a/longest-common-subsequence/pmjuu.py b/longest-common-subsequence/pmjuu.py new file mode 100644 index 000000000..74e729d85 --- /dev/null +++ b/longest-common-subsequence/pmjuu.py @@ -0,0 +1,20 @@ +''' +시간 복잡도: O(m * n) +공간 복잡도: O(n) +''' + +class Solution: + def longestCommonSubsequence(self, text1: str, text2: str) -> int: + m, n = len(text1), len(text2) + prev = [0] * (n + 1) + + for i in range(1, m + 1): + curr = [0] * (n + 1) + for j in range(1, n + 1): + if text1[i - 1] == text2[j - 1]: + curr[j] = prev[j - 1] + 1 + else: + curr[j] = max(prev[j], curr[j - 1]) + prev = curr # 현재 행을 이전 행으로 업데이트 + + return prev[n] diff --git a/longest-repeating-character-replacement/pmjuu.py b/longest-repeating-character-replacement/pmjuu.py new file mode 100644 index 000000000..fd762343c --- /dev/null +++ b/longest-repeating-character-replacement/pmjuu.py @@ -0,0 +1,26 @@ +''' +시간복잡도: O(n) +- 문자열의 길이만큼 한 번만 순회합니다. +공간복잡도: O(n) +- char_count 딕셔너리는 최대 알파벳 26개만 저장합니다. +''' + +class Solution: + def characterReplacement(self, s: str, k: int) -> int: + left = 0 + max_count = 0 + max_length = 0 + char_count = {} + + for right in range(len(s)): + char_count[s[right]] = char_count.get(s[right], 0) + 1 + max_count = max(max_count, char_count[s[right]]) + + # If the remaining characters exceed the allowed k changes + while (right - left + 1) - max_count > k: + char_count[s[left]] -= 1 + left += 1 + + max_length = max(max_length, right - left + 1) + + return max_length diff --git a/number-of-1-bits/pmjuu.py b/number-of-1-bits/pmjuu.py new file mode 100644 index 000000000..da583bfd9 --- /dev/null +++ b/number-of-1-bits/pmjuu.py @@ -0,0 +1,23 @@ +''' +시간 복잡도 +- format(n, 'b'): 정수를 이진 문자열로 변환하는 작업은 O(k)입니다. +- Counter(bits): 문자열을 순회하면서 각 문자의 빈도를 계산하며, 이 작업도 문자열 길이 k에 비례합니다. +- count['1']: 딕셔너리 조회는 상수 시간이므로 O(1)입니다. + +총 시간 복잡도: O(k) + O(k) + O(1) = O(k) + +공간 복잡도 +- format(n, 'b'): 생성된 이진 문자열은 길이 k를 차지합니다. +- Counter(bits): 딕셔너리 형태로 각 문자의 빈도를 저장합니다. 최악의 경우, 두 가지 문자(‘0’과 ‘1’)만 있으므로 공간 복잡도는 O(2) = O(1)로 간주할 수 있습니다. + +총 공간 복잡도: O(k) +''' + +from collections import Counter + +class Solution: + def hammingWeight(self, n: int) -> int: + bits = format(n, 'b') + count = Counter(bits) + + return count['1'] diff --git a/sum-of-two-integers/pmjuu.py b/sum-of-two-integers/pmjuu.py new file mode 100644 index 000000000..927876cfa --- /dev/null +++ b/sum-of-two-integers/pmjuu.py @@ -0,0 +1,20 @@ +''' +시간 복잡도: O(1) +- 덧셈은 비트 연산을 이용하여 수행되며, 정수 크기가 고정되어 있기 때문에 연산 횟수가 제한적입니다. + +공간 복잡도: O(1) +- 추가적인 메모리를 거의 사용하지 않습니다. +''' + +class Solution: + def getSum(self, a: int, b: int) -> int: + MASK = 0xFFFFFFFF # 32비트 정수 마스크 + MAX_INT = 0x7FFFFFFF # 32비트 정수의 최대값 + + while b: + carry = (a & b) << 1 # 자리 올림 계산 + a = (a ^ b) & MASK # 덧셈 수행 + b = carry & MASK # 자리 올림값을 반영하여 다음 연산 진행 + + # 음수 처리를 위해 32비트 초과 시 보정 + return a if a <= MAX_INT else ~(a ^ MASK)