From 9c6d65133e112adc78ebce742f7224b12a193614 Mon Sep 17 00:00:00 2001 From: river20s Date: Thu, 22 May 2025 01:04:42 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20Add=20Solution=20to=20Reverse=20Bit?= =?UTF-8?q?s=20#234=20-=20=EB=A3=A9=EC=97=85=20=ED=85=8C=EC=9D=B4=EB=B8=94?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9=ED=95=98=EC=97=AC=20follow=20up=20?= =?UTF-8?q?=EC=A7=88=EB=AC=B8=20=EB=8B=B5=EC=95=88=20=EC=9E=91=EC=84=B1?= =?UTF-8?q?=ED=95=B4=EB=B3=B4=EC=95=98=EC=8A=B5=EB=8B=88=EB=8B=A4.=20-=20?= =?UTF-8?q?=EA=B8=B0=EB=B3=B8=EC=A0=81=EC=9D=B8=20=EB=B9=84=ED=8A=B8=20?= =?UTF-8?q?=EC=97=B0=EC=82=B0=EC=9E=90=20=EC=82=AC=EC=9A=A9=ED=95=B4?= =?UTF-8?q?=EC=84=9C=20=EC=88=9C=ED=9A=8C=ED=95=98=EB=A9=B0=20=EB=92=A4?= =?UTF-8?q?=EC=A7=91=EB=8A=94=20=EB=A1=9C=EC=A7=81=EC=9D=84=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=EC=9C=BC=EB=A1=9C=20=EB=91=90=EC=97=88=EC=8A=B5?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- reverse-bits/river20s.py | 59 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 reverse-bits/river20s.py diff --git a/reverse-bits/river20s.py b/reverse-bits/river20s.py new file mode 100644 index 000000000..acd8a9479 --- /dev/null +++ b/reverse-bits/river20s.py @@ -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 From 21817ba84301a8565ae3c81574a5168946c6527c Mon Sep 17 00:00:00 2001 From: river20s Date: Thu, 22 May 2025 01:20:19 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20Add=20Solution=20to=20Longest=20Rea?= =?UTF-8?q?peating=20Character=20Replacement=20#244=20-=20=EC=8A=AC?= =?UTF-8?q?=EB=9D=BC=EC=9D=B4=EB=94=A9=20=EC=9C=88=EB=8F=84=EC=9A=B0?= =?UTF-8?q?=EB=A5=BC=20=EC=A0=81=EC=9A=A9=ED=95=98=EC=97=AC=20=EB=8B=B5?= =?UTF-8?q?=EC=95=88=EC=9D=84=20=EC=9E=91=EC=84=B1=ED=96=88=EC=8A=B5?= =?UTF-8?q?=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../river20s.py | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 longest-repeating-character-replacement/river20s.py diff --git a/longest-repeating-character-replacement/river20s.py b/longest-repeating-character-replacement/river20s.py new file mode 100644 index 000000000..d2de1ffd4 --- /dev/null +++ b/longest-repeating-character-replacement/river20s.py @@ -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 From 98f8c3e4eaf18174c59d5f3fbda5a1140151758c Mon Sep 17 00:00:00 2001 From: river20s Date: Fri, 23 May 2025 00:52:32 +0900 Subject: [PATCH 3/4] feat: Add Solution to Clone Graph #259 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 원본 노드 객체를 key로, 복사본 노드 객체를 value로 갖는 clones_map을 사용해 이미 복제되었는지 체크하도록 합니다. - DFS를 활용해 재귀적으로 깊은 복사를 수행하는 dfs_clone() 함수를 작성했습니다. clones_map에 지금 보고 있는 원본 노드가 있다면 바로 복사본 노드를 반환합니다. - 새 노드를 만들고 val을 복사한 후, 곧바로 clones_map에 매핑하도록 하여 무한 루프를 방지했습니다.(그래프가 연결되어 있어, 이웃을 복제하다가 계속해서 재귀 호출하는 경우 방지) --- clone-graph/river20s.py | 49 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 clone-graph/river20s.py diff --git a/clone-graph/river20s.py b/clone-graph/river20s.py new file mode 100644 index 000000000..346ec5643 --- /dev/null +++ b/clone-graph/river20s.py @@ -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) From 493fab72d5f4b1321d3b540c89c60dcfea4da94f Mon Sep 17 00:00:00 2001 From: river20s Date: Sat, 24 May 2025 16:48:45 +0900 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20Add=20Solution=20to=20Palindromic?= =?UTF-8?q?=20Substrings=20-=20=EB=B8=8C=EB=A3=A8=ED=8A=B8=20=ED=8F=AC?= =?UTF-8?q?=EC=8A=A4=EB=A1=9C=20=EA=B5=AC=ED=98=84=ED=95=98=EC=98=80?= =?UTF-8?q?=EB=8B=A4=EA=B0=80,=20=EB=B3=B5=EC=9E=A1=EB=8F=84=EA=B0=80=20O(?= =?UTF-8?q?n^3)=EC=9D=B4=20=EB=90=98=EC=96=B4=20=ED=95=B4=EC=84=A4?= =?UTF-8?q?=EC=9D=84=20=EB=B3=B4=EA=B3=A0=20=EC=B5=9C=EC=A0=81=ED=99=94=20?= =?UTF-8?q?=ED=95=98=EC=98=80=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- palindromic-substrings/river20s.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 palindromic-substrings/river20s.py diff --git a/palindromic-substrings/river20s.py b/palindromic-substrings/river20s.py new file mode 100644 index 000000000..6aedd6f70 --- /dev/null +++ b/palindromic-substrings/river20s.py @@ -0,0 +1,28 @@ +class Solution: + def countSubstrings(self, s: str) -> int: + """ + Time Complexity: O(n^2) + Space Complexity: O(1) + """ + n = len(s) + if n == 0: + return 0 + + count = 0 + + for i in range(n): + # 중심이 하나(홀수 길이 회문) + left, right = i, i + while left >= 0 and right < n and s[left] == s[right]: + count += 1 + left -= 1 + right += 1 + + # 중심이 둘 사이(짝수 길이 회문) + left, right = i, i + 1 + while left >= 0 and right < n and s[left] == s[right]: + count += 1 + left -= 1 + right += 1 + + return count