From f3219760f06956af0527ad2d17109a15e46f599b Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Sun, 19 Apr 2026 23:21:29 +0900 Subject: [PATCH 1/6] [7th batch] week 7 - set matrix zero --- set-matrix-zeroes/liza0525.py | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 set-matrix-zeroes/liza0525.py diff --git a/set-matrix-zeroes/liza0525.py b/set-matrix-zeroes/liza0525.py new file mode 100644 index 000000000..b2651c878 --- /dev/null +++ b/set-matrix-zeroes/liza0525.py @@ -0,0 +1,33 @@ +# 7기 풀이 +# 시간 복잡도: O(m * n) +# - matrix 크기 만큼 시간 복잡도가 듦 +# 공간 복잡도: O(m + n) +# - 가로, 세로에서 각각 대상 인덱스를 저장 +class Solution: + def setZeroes(self, matrix: List[List[int]]) -> None: + """ + Do not return anything, modify matrix in-place instead. + """ + len_i = len(matrix) + len_j = len(matrix[0]) + + # 0이 발견된 행/열 인덱스를 각각 저장하는 set + target_i_set, target_j_set = set(), set() + + for i in range(len_i): + for j in range(len_j): + if matrix[i][j] != 0: + continue + + # matrix[i][j]가 0인 경우에는 인덱스를 저장한다. + target_i_set.add(i) + target_j_set.add(j) + + + for i in range(len_i): + for j in range(len_j): + if matrix[i][j] == 0: + continue + if i in target_i_set or j in target_j_set: + # i, j 인덱스가 set에 있는 경우에는 0으로 변경한다. + matrix[i][j] = 0 From 9be1187368681bfde6556c9a36de46c4afda681d Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Fri, 24 Apr 2026 14:11:46 +0900 Subject: [PATCH 2/6] [7th batch] week 8 - reverse bits --- reverse-bits/liza0525.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 reverse-bits/liza0525.py diff --git a/reverse-bits/liza0525.py b/reverse-bits/liza0525.py new file mode 100644 index 000000000..fe2deaf3a --- /dev/null +++ b/reverse-bits/liza0525.py @@ -0,0 +1,25 @@ +# 7기 풀이 +# 시간 복잡도: O(1) +# - 해당 문제는 조건 자체가 32자릿수로 되어 있어 최대 32번까지만 계산 +# 공간 복잡도: O(1) +# - result, idx와 같은 변수만 사용 +class Solution: + def reverseBits(self, n: int) -> int: + result = 0 + idx = 0 # 자릿수 계산을 위한 앵커 + + while n > 0: # n이 0이 되기 전까지 돌린다. + remainder = n % 2 # 수를 2로 나눴을 때의 나머지가 해당 자리수에서의 2진수 값 (0 or 1) + quotient = n // 2 # 몫은 다음 루프의 피젯수로 + + if remainder: + # 나머지가 있는 경우에는 해당 2진수 자리수에 값이 있다. + # reversed한 값을 계산해야 하기 때문에 32 - idx - 1의 자릿수로 변환 + # (문제 조건 상 32자릿수가 기준) + # 변환한 후 result에 값을 더해준다. + result += 2 ** (32 - idx - 1) + + n = quotient + idx += 1 # 자릿수를 하나 올린다 + + return result From e793bf4760b6b4db889028e6af1fb06a7cc99067 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Fri, 24 Apr 2026 14:46:17 +0900 Subject: [PATCH 3/6] [7th batch] week 8 - clone graph --- clone-graph/liza0525.py | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 clone-graph/liza0525.py diff --git a/clone-graph/liza0525.py b/clone-graph/liza0525.py new file mode 100644 index 000000000..a57cafa36 --- /dev/null +++ b/clone-graph/liza0525.py @@ -0,0 +1,46 @@ +from typing import Optional + +# 7기 풀이 +# 시간 복잡도: O(V + E) +# - 모든 노드의 수와 모든 엣지의 수만큼 탐방하므로 그만큼의 시간이 걸림(V: 노드 수, E: 엣지 수) +# 공간 복잡도: O(V) +# - memo에 모든 노드를 복사해서 추가(V: 노드의 갯수) +class Solution: + def cloneGraph(self, node: Optional['Node']) -> Optional['Node']: + memo = {} + + def copy_graph(node): + if not node: + # 더이상 복사할 노드가 없다면 None을 return + return None + + if node.val in memo: + # node의 값이 memo에 있다면 memo에 있는 값을 return + return memo[node.val] + + # Node의 복사를 위해 새 노드 생성 및 node.val 값을 초기값으로 입력 + res_node = Node(node.val) + memo[node.val] = res_node # memo에 새로만든 객체를 value로 하여 저장(key는 node.val 값으로) + + # neighbors도 복사, 이 때 copy_graph를 재귀로 호출하여 모든 neighbors들을 복사하도록 한다. + res_node.neighbors = [ + copy_graph(neighbor) for neighbor in node.neighbors + ] + + # res_node를 return + return res_node + + return copy_graph(node)# 다음과 같이 파이썬의 built-in 함수인 deepcopy를 사용하면 바로 문제가 풀리기도 했다. + + +# 정리 목적 +# 다음과 같이 파이썬의 built-in 함수인 deepcopy를 사용하면 바로 문제가 풀리기도 했다. +# 실제 deepcopy 구현이 memo를 이용하며 +# copier의 deepcopy를 호출하여 재귀와 비슷하게 구현했다는 것을 확인할 수 있었다 +# ref: https://github.com/python/cpython/blob/main/Lib/copy.py +from copy import deepcopy + + +class Solution: + def cloneGraph(self, node: Optional['Node']) -> Optional['Node']: + return deepcopy(node) From bbc338e6ec5e603e710ff67d33beeb08975f5321 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Fri, 24 Apr 2026 15:01:44 +0900 Subject: [PATCH 4/6] [7th batch] week 8 - palindrome substrings --- palindromic-substrings/liza0525.py | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 palindromic-substrings/liza0525.py diff --git a/palindromic-substrings/liza0525.py b/palindromic-substrings/liza0525.py new file mode 100644 index 000000000..ff0f6499d --- /dev/null +++ b/palindromic-substrings/liza0525.py @@ -0,0 +1,32 @@ +# 7기 풀이 +# 시간 복잡도: O(n ** 2) +# - for문으로 문자의 중심을 탐색 * while문으로 양쪽으로 뻗어나가며 문자열 탐색 +# 공간 복잡도: O(1) +# - 변수 몇 개만 사용 +class Solution: + # 해당 문제의 기본 아이디어: 중심 확장법을 이용하여 펠린드롬 찾기 + def countSubstrings(self, s: str) -> int: + res = 0 + + # 펠린드롬의 길이가 짝수일 수도 홀수일 수도 있기 때문에 + # 2 * len(s)를 돌고 나눈 수 몫을 이용해서 중심을 먼저 잡는다 + for idx in range(2 * len(s) - 1): + # 펠린드롬 길이가 짝수일 때는 left와 right의 값이 1 차이나지만 + # 홀수일 때는 left == right 이다. + left = idx // 2 + right = (idx + 1) // 2 + delta = 0 + + while ( + 0 <= left - delta # 왼쪽으로 확장했을 때의 index와 + and right + delta < len(s) # 오른쪽으로 확장했을 때의 index가 모두 s길이 범위 내에 있어야 함 + ): + if s[left - delta] == s[right + delta]: # 두 개가 같은 경우에는 펠린드롬 + res += 1 # 결과 값을 하나 추가하고 + delta += 1 # 확장을 위한 값을 1 올려준다 + else: + # 확장했을 때의 양 쪽 문자가 다른 경우에는 펠린드롬이 아니므로 break하고 + # 다음 루프에서 새로운 중심을 잡은 후 다시 펠린드롬을 찾는다. + break + + return res From 775b2afd15bd5c4278c430bf8d7e0d3b315c58ff Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Fri, 24 Apr 2026 15:20:08 +0900 Subject: [PATCH 5/6] [7th batch] week 8 - longest repeating characer replacement --- .../liza0525.py | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 longest-repeating-character-replacement/liza0525.py diff --git a/longest-repeating-character-replacement/liza0525.py b/longest-repeating-character-replacement/liza0525.py new file mode 100644 index 000000000..0ac472617 --- /dev/null +++ b/longest-repeating-character-replacement/liza0525.py @@ -0,0 +1,32 @@ +from collections import defaultdict + + +# 7기 풀이 +# 시간 복잡도: O(n) +# - right는 매 루프마다 전진하고 left도 최대 n번 전진하므로 합쳐서 O(n) +# 공간 복잡도: O(1) +# - s에 있는 문자들의 개수만큼 공간 복잡도가 늘어나겠지만 모두 대문자인 알파벳만이 key로 들어오므로 최대 26개 +class Solution: + # 기본 아이디어: 슬라이딩 윈도우를 사용하면서 + # 윈도우 내에 가장 많이 있는 문자의 개수와 k값을 더한 값이 윈도우를 초과하는지 아닌지를 확인 + def characterReplacement(self, s: str, k: int) -> int: + left = 0 # 윈도우 왼쪽 인덱스 값 + max_len = 0 # 문제의 답(변경 시 가장 긴 substring 길이) + char_dict = defaultdict(int) # 윈도우 내의 각 문자들 개수를 확인하기 위한 dict + max_char_cnt = 0 # 윈도우 내에 가장 많은 문자의 개수 그 자체(dict의 value() 메서드를 매번 호출하지 않게 하기 위함) + + for right in range(len(s)): # 윈도우 오른쪽 인덱스 값 + char_dict[s[right]] += 1 # 오른쪽 인덱스에 해당하는 문자(예: A)에 대한 개수를 하나 올림 + max_char_cnt = max(max_char_cnt, char_dict[s[right]]) # 현재 윈도우에서 가장 많은 문자의 개수를 업데이트 + + if max_char_cnt + k >= right - left + 1: + # 가장 많은 문자열 사이에 있는 다른 문자들의 개수가 k보다 작으면 변경 가능 + # -> 윈도우 내에서 가장 긴 repeating substring을 만들 수 있음 + max_len = max(max_len, right - left + 1) + else: + # 만들 수 없는 경우에는 기존 left의 문자를 char_dict로부터 하나 줄이고 + # left를 하나 옮긴다(새로운 윈도우를 만든다는 의미) + char_dict[s[left]] -= 1 + left += 1 + + return max_len From c8b2d2a508a5bf25e704aed971a0c423f81da065 Mon Sep 17 00:00:00 2001 From: Yunyoung Chung Date: Fri, 24 Apr 2026 15:31:16 +0900 Subject: [PATCH 6/6] [7th batch] week 8 - longest common subsequence --- longest-common-subsequence/liza0525.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 longest-common-subsequence/liza0525.py diff --git a/longest-common-subsequence/liza0525.py b/longest-common-subsequence/liza0525.py new file mode 100644 index 000000000..059695323 --- /dev/null +++ b/longest-common-subsequence/liza0525.py @@ -0,0 +1,26 @@ +# 7기 풀이 +# 시간 복잡도: O(n * m) +# - text1의 길이 n과 text2의 길이 m만큼 순회하며 계산함 +# 공간 복잡도: O(n * m) +# - text1의 길이 n과 text2의 길이 m만큼의 2차 배열을 만들어 DP 계산을 하기 때문 +class Solution: + def longestCommonSubsequence(self, text1: str, text2: str) -> int: + dp = [ + [0 for _ in range(len(text2) + 1)] + for _ in range(len(text1) + 1) + ] + + for i in range(1, len(text1) + 1): + for j in range(1, len(text2) + 1): + if text1[i - 1] == text2[j - 1]: + # text1의 i번째 문자와 text2의 j번째 문자가 같다면 + # 이 문자는 공통 subsequence에 포함될 수 있으므로 + # 두 문자를 제외한 나머지(dp[i-1][j-1])에 1을 더한 값이 현재의 LCS 길이가 된다 + dp[i][j] = dp[i - 1][j - 1] + 1 + else: + # 같지 않다면 둘 중 하나를 제외했을 때의 LCS 중 더 큰 값을 가져온다 + # dp[i][j-1]: text2의 j번째 문자를 제외한 경우 + # dp[i-1][j]: text1의 i번째 문자를 제외한 경우 + dp[i][j] = max(dp[i][j - 1], dp[i - 1][j]) + + return dp[-1][-1]