diff --git a/clone-graph/Chaedie.py b/clone-graph/Chaedie.py new file mode 100644 index 000000000..0a748f37f --- /dev/null +++ b/clone-graph/Chaedie.py @@ -0,0 +1,32 @@ +""" +한번에 풀지 못해 다시 풀어볼 예정입니다. + +Solution: + 1) oldToNew 라는 dict 를 만들어 무한루프를 방지합니다. + 2) newNode = Node(node.val), newNode.neighbors.append(dfs(nei)) 를 통해 clone을 구현합니다. + +정점 V, 간선 E +Time: O(V + E) +Space: O(V + E) +""" + + +class Solution: + def cloneGraph(self, root: Optional["Node"]) -> Optional["Node"]: + if not root: + return None + oldToNew = {} + + def dfs(node): + if node in oldToNew: + return oldToNew[node] + + newNode = Node(node.val) + oldToNew[node] = newNode + + for nei in node.neighbors: + newNode.neighbors.append(dfs(nei)) + + return newNode + + return dfs(root) diff --git a/longest-common-subsequence/Chaedie.py b/longest-common-subsequence/Chaedie.py new file mode 100644 index 000000000..6661448cc --- /dev/null +++ b/longest-common-subsequence/Chaedie.py @@ -0,0 +1,25 @@ +""" +Solution: 재귀를 활용한 풀이, memo 를 활용한 시간복잡도 개선 + +Time: O(m * n) +Space: O(2 * m * n) +""" + + +class Solution: + def longestCommonSubsequence(self, text1: str, text2: str) -> int: + memo = {} + + def dfs(i, j): + if (i, j) in memo: + return memo[(i, j)] + + if i == len(text1) or j == len(text2): + memo[(i, j)] = 0 + elif text1[i] == text2[j]: + memo[(i, j)] = 1 + dfs(i + 1, j + 1) + else: + memo[(i, j)] = max(dfs(i + 1, j), dfs(i, j + 1)) + return memo[(i, j)] + + return dfs(0, 0) diff --git a/longest-repeating-character-replacement/Chaedie.py b/longest-repeating-character-replacement/Chaedie.py new file mode 100644 index 000000000..8e7e8264c --- /dev/null +++ b/longest-repeating-character-replacement/Chaedie.py @@ -0,0 +1,31 @@ +""" +Solution: + 1) sliding window 활용 + 2) window 에 들어가는 글자들은 counts 라는 hash map 으로 갯수를 세어준다. + 3) 순회를 하면서 window size 가 counts에서 가장 큰숫자 + k 보다 크면 invalid window 이기에 left 글자 갯수를 빼고 포인터를 이동해준다. + 4) max_count 는 기존 max 값과 현재 window 사이즈 중 큰 숫자를 셋해준다. + +Time: O(n) = O(26n) +Space: O(1) = O(26) +""" + + +class Solution: + def characterReplacement(self, s: str, k: int) -> int: + counts = defaultdict(int) + max_count = 0 + + l, r = 0, 0 + while l <= r and r < len(s): + counts[s[r]] += 1 + window_size = r - l + 1 + + if window_size > max(counts.values()) + k: + counts[s[l]] -= 1 + l += 1 + + window_size = r - l + 1 + max_count = max(window_size, max_count) + r += 1 + + return max_count diff --git a/longest-substring-without-repeating-characters/Chaedie.py b/longest-substring-without-repeating-characters/Chaedie.py index 2d8185449..b5ec50a89 100644 --- a/longest-substring-without-repeating-characters/Chaedie.py +++ b/longest-substring-without-repeating-characters/Chaedie.py @@ -3,7 +3,7 @@ 1) for iteration 을 도는 동안 hash set 을 이용해 처음 발견한 원소들을 window set에 넣는다. 2) 중복되는 원소를 발견할 경우 해당 원소의 중복이 사라질때까지 left side 의 원소들을 하나씩 제거한다. -Time: O(n^2) = O(n) (for iteration) * O(n) 최악의 경우 n만큼의 중복제거 +Time: O(2n) = O(n) (최악의 경우 n만큼의 중복제거) * O(2) (원소당 최대 2번의 연산) Space: O(n) (모든 원소가 set에 들어갈 경우) """ diff --git a/number-of-1-bits/Chaedie.py b/number-of-1-bits/Chaedie.py new file mode 100644 index 000000000..96f169c88 --- /dev/null +++ b/number-of-1-bits/Chaedie.py @@ -0,0 +1,20 @@ +""" +Solution: + 1) 숫자에 1 bit 을 and 연산 결과가 1일 경우 result 에 1을 더한다. + 2) n 을 오른쪽으로 쉬프팅 시킨다. + +N: n의 bit 수 +Time: O(N) +Space: O(1) + +""" + + +class Solution: + def hammingWeight(self, n: int) -> int: + result = 0 + while n > 0: + if n & 1: + result += 1 + n = n >> 1 + return result diff --git a/reverse-linked-list/Chaedie.py b/reverse-linked-list/Chaedie.py index c368ee95f..9af3c8e0f 100644 --- a/reverse-linked-list/Chaedie.py +++ b/reverse-linked-list/Chaedie.py @@ -1,9 +1,9 @@ """ Solution: - 1) next node를 저장합니다. + 1) temp node를 저장합니다. 2) cur node 를 prev node 로 연결시킵니다. 3) cur node 가 prev node 가 됩니다. - 4) cur node 는 next node 가 됩니다. + 4) cur node 는 temp node 가 됩니다. Time: O(n) Space: O(1) """ @@ -14,8 +14,8 @@ def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]: prev = None cur = head while cur: - next = cur.next + temp = cur.next cur.next = prev prev = cur - cur = next + cur = temp return prev diff --git a/sum-of-two-integers/Chaedie.py b/sum-of-two-integers/Chaedie.py new file mode 100644 index 000000000..1d5c0330e --- /dev/null +++ b/sum-of-two-integers/Chaedie.py @@ -0,0 +1,18 @@ +""" +Solution: 해설을 활용한 풀이입니다. + 1) xor 로 더하기를 만들 수있다. + 2) & << 1 로 carry 를 만들 수 있다. + 3) python 의 경우 32비트 마스크를 사용해 음수 케이스를 고려한다. + +""" + + +class Solution: + def getSum(self, a: int, b: int) -> int: + mask = 0xFFFFFFFF + + xor = a ^ b + carry = (a & b) << 1 + while carry & mask: + xor, carry = xor ^ carry, (xor & carry) << 1 + return (xor & mask) if carry > 0 else xor diff --git a/unique-paths/Chaedie.py b/unique-paths/Chaedie.py index 7bd0bc4c0..9f7e6c7ac 100644 --- a/unique-paths/Chaedie.py +++ b/unique-paths/Chaedie.py @@ -17,7 +17,6 @@ def uniquePaths(self, m: int, n: int) -> int: dp = [] for i in range(m): dp.append([0] * n) - print(dp) for i in range(m): for j in range(n): @@ -31,3 +30,24 @@ def uniquePaths(self, m: int, n: int) -> int: dp[i][j] = up_value + left_value return dp[m - 1][n - 1] + + +""" +* 7주차에 받은 리뷰사항 뒤늦게 반영합니다. +Solution: + 1) dp를 1로 m*n 배열로 초기화 + 2) 순회를 1부터 m, 1부터 n까지로 변경 + 3) up_value, left_value 를 Out of bounds 처리 없이 dp 배열로 계산 + +""" + + +class Solution: + def uniquePaths(self, m: int, n: int) -> int: + dp = [[1] * n] * m + + for i in range(1, m): + for j in range(1, n): + dp[i][j] = dp[i - 1][j] + dp[i][j - 1] + + return dp[m - 1][n - 1]