diff --git a/binary-tree-level-order-traversal/pmjuu.py b/binary-tree-level-order-traversal/pmjuu.py new file mode 100644 index 000000000..38ab31de2 --- /dev/null +++ b/binary-tree-level-order-traversal/pmjuu.py @@ -0,0 +1,34 @@ +''' +시간 복잡도: O(n) +공간 복잡도: O(n) +''' + +from collections import deque +from typing import List, Optional + +class TreeNode: + def __init__(self, val=0, left=None, right=None): + self.val = val + self.left = left + self.right = right + +class Solution: + def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: + queue = deque([root]) if root else [] + result = [] + + while queue: + same_level_nodes = [] + + for _ in range(len(queue)): + node = queue.popleft() + same_level_nodes.append(node.val) + + if node.left: + queue.append(node.left) + if node.right: + queue.append(node.right) + + result.append(same_level_nodes) + + return result diff --git a/counting-bits/pmjuu.py b/counting-bits/pmjuu.py new file mode 100644 index 000000000..1e749dcb6 --- /dev/null +++ b/counting-bits/pmjuu.py @@ -0,0 +1,15 @@ +''' +시간 복잡도: O(n) +공간 복잡도: O(n) +''' +from typing import List + + +class Solution: + def countBits(self, n: int) -> List[int]: + dp = [0] * (n + 1) + + for i in range(1, n + 1): + dp[i] = dp[i >> 1] + (i & 1) + + return dp diff --git a/house-robber-ii/pmjuu.py b/house-robber-ii/pmjuu.py new file mode 100644 index 000000000..9d2e355a5 --- /dev/null +++ b/house-robber-ii/pmjuu.py @@ -0,0 +1,25 @@ +''' +시간 복잡도: O(n) +공간 복잡도: O(n) +''' +from typing import List + +class Solution: + def rob(self, nums: List[int]) -> int: + n = len(nums) + if n == 1: + return nums[0] + if n == 2: + return max(nums[0], nums[1]) + + dp_first = [0] * n + dp_second = [0] * n + + dp_first[0], dp_first[1] = nums[0], max(nums[0], nums[1]) + dp_second[1], dp_second[2] = nums[1], max(nums[1], nums[2]) + + for i in range(2, n): + dp_first[i] = max(dp_first[i - 1], dp_first[i - 2] + nums[i]) + dp_second[i] = max(dp_second[i - 1], dp_second[i - 2] + nums[i]) + + return max(dp_first[-2], dp_second[-1]) diff --git a/meeting-rooms-ii/pmjuu.py b/meeting-rooms-ii/pmjuu.py new file mode 100644 index 000000000..9ef7d2e60 --- /dev/null +++ b/meeting-rooms-ii/pmjuu.py @@ -0,0 +1,98 @@ +''' +시간 복잡도: O(n log n) +공간 복잡도: O(n) +''' +from typing import List +from heapq import heappush, heappop + +class Interval(object): + def __init__(self, start, end): + self.start = start + self.end = end + +class Solution: + def min_meeting_rooms(self, intervals: List[Interval]) -> int: + intervals.sort(key=lambda x:x.start) + ends = [] + + for interval in intervals: + if ends and ends[0] <= interval.start: + heappop(ends) + + heappush(ends, interval.end) + + return len(ends) + + +def run_tests(): + solution = Solution() + + test_cases = [ + # Test Case 1: 문제의 Example 1 + { + "input": [Interval(0, 30), Interval(5, 10), Interval(15, 20)], + "expected": 2, + "description": "Example 1: [(0,30), (5,10), (15,20)] - 2 rooms needed" + }, + # Test Case 2: 문제의 Example 2 + { + "input": [Interval(2, 7)], + "expected": 1, + "description": "Example 2: [(2,7)] - 1 room needed" + }, + # Test Case 3: 겹치지 않는 회의들 + { + "input": [Interval(0, 8), Interval(8, 10), Interval(10, 12)], + "expected": 1, + "description": "Non-overlapping meetings: [(0,8), (8,10), (10,12)]" + }, + # Test Case 4: 모든 회의가 겹치는 경우 + { + "input": [Interval(1, 5), Interval(2, 6), Interval(3, 7)], + "expected": 3, + "description": "All overlapping: [(1,5), (2,6), (3,7)]" + }, + # Test Case 5: 빈 입력 + { + "input": [], + "expected": 0, + "description": "Empty input: []" + }, + # Test Case 6: 복잡한 경우 + { + "input": [Interval(1, 10), Interval(2, 7), Interval(3, 19), Interval(8, 12)], + "expected": 3, + "description": "Complex case: [(1,10), (2,7), (3,19), (8,12)]" + }, + { + "input": [Interval(1, 4), Interval(2, 5), Interval(3, 6)], + "expected": 3, + "description": "Multiple overlaps: [(1,4), (2,5), (3,6)]" + }, + { + "input": [Interval(1, 10), Interval(2, 3), Interval(4, 5), Interval(6, 7)], + "expected": 2, + "description": "Short and long meetings: [(1,10), (2,3), (4,5), (6,7)]" + }, + { + "input": [Interval(1, 5), Interval(5, 10), Interval(10, 15), Interval(2, 7)], + "expected": 2, + "description": "Mixed overlaps: [(1,5), (5,10), (10,15), (2,7)]" + } + ] + + # 테스트 실행 + for i, test in enumerate(test_cases, 1): + intervals = test["input"] + expected = test["expected"] + result = solution.min_meeting_rooms(intervals) + + print(f"Test Case {i}: {test['description']}") + print(f"Input: {[(interval.start, interval.end) for interval in intervals]}") + print(f"Expected Output: {expected}") + print(f"Your Output: {result}") + print(f"Result: {'✅ PASS' if result == expected else '❌ FAIL'}") + print("-" * 50) + +if __name__ == "__main__": + run_tests() diff --git a/word-search-ii/pmjuu.py b/word-search-ii/pmjuu.py new file mode 100644 index 000000000..905ca631e --- /dev/null +++ b/word-search-ii/pmjuu.py @@ -0,0 +1,46 @@ +''' +시간 복잡도: O(m * n * 4^s) s = word 최대 길이 +공간 복잡도: O(w) w = 모든 단어에 포함된 문자 수의 합 +''' +from typing import List + +class Solution: + def findWords(self, board: List[List[str]], words: List[str]) -> List[str]: + root = {} + for word in words: + node = root + + for char in word: + if char not in node: + node[char] = {} + node = node[char] + + node['$'] = word + + def dfs(i, j, node, visited): + if '$' in node: + result.append(node['$']) + del node['$'] + + if not (0 <= i < m and 0 <= j < n) or (i, j) in visited: + return + + char = board[i][j] + if char not in node: + return + + visited.add((i, j)) + + for di, dj in [(0, 1), (1, 0), (0, -1), (-1, 0)]: + dfs(i + di, j + dj, node[char], visited) + + visited.remove((i, j)) + + m, n = len(board), len(board[0]) + result = [] + + for i in range(m): + for j in range(n): + dfs(i, j, root, set()) + + return result