diff --git a/binary-tree-level-order-traversal/imsosleepy.java b/binary-tree-level-order-traversal/imsosleepy.java index c94b68ee4..6e8995cc2 100644 --- a/binary-tree-level-order-traversal/imsosleepy.java +++ b/binary-tree-level-order-traversal/imsosleepy.java @@ -1,27 +1,29 @@ -// dfs와 분할 정복법으로 해결되는 문제 -// dfs인 것을 알았으나 모든 숫자가 음수일 경우를 판별하지 못해 GPT에게 도움을 처함 +// 그동안의 대부분의 트리문제는 DFS로 해결 됐어서.. 그렇게 해야하 싶었는데 +// 가로로 나열되기 때문에 BFS가 적합함 +// 한번의 순회로 해결되기 때문에 시간 복잡도는 O(N) class Solution { - private int maxSum = Integer.MIN_VALUE; // 전체 최대 경로 합 저장 + public List> levelOrder(TreeNode root) { + List> result = new ArrayList<>(); + if (root == null) return result; - public int maxPathSum(TreeNode root) { - dfs(root); - return maxSum; - } + Queue queue = new LinkedList<>(); + queue.offer(root); - private int dfs(TreeNode node) { - if (node == null) return 0; // base case + while (!queue.isEmpty()) { + int levelSize = queue.size(); + List level = new ArrayList<>(); - // 왼쪽, 오른쪽 서브트리의 최대 경로 합 (음수는 포함 X → Math.max(0, value)) - int left = Math.max(0, dfs(node.left)); - int right = Math.max(0, dfs(node.right)); + for (int i = 0; i < levelSize; i++) { + TreeNode node = queue.poll(); + level.add(node.val); - // 현재 노드를 포함한 최대 경로 (왼쪽 + 루트 + 오른쪽) - int pathSum = left + node.val + right; + if (node.left != null) queue.offer(node.left); + if (node.right != null) queue.offer(node.right); + } - // 최대 경로 값 갱신 - maxSum = Math.max(maxSum, pathSum); + result.add(level); + } - // ✅ 현재 노드를 포함하는 최대 경로 값만 반환해야 함 (연결 가능한 경로) - return node.val + Math.max(left, right); + return result; } } diff --git a/binary-tree-maximum-path-sum/imsosleepy.java b/binary-tree-maximum-path-sum/imsosleepy.java new file mode 100644 index 000000000..c94b68ee4 --- /dev/null +++ b/binary-tree-maximum-path-sum/imsosleepy.java @@ -0,0 +1,27 @@ +// dfs와 분할 정복법으로 해결되는 문제 +// dfs인 것을 알았으나 모든 숫자가 음수일 경우를 판별하지 못해 GPT에게 도움을 처함 +class Solution { + private int maxSum = Integer.MIN_VALUE; // 전체 최대 경로 합 저장 + + public int maxPathSum(TreeNode root) { + dfs(root); + return maxSum; + } + + private int dfs(TreeNode node) { + if (node == null) return 0; // base case + + // 왼쪽, 오른쪽 서브트리의 최대 경로 합 (음수는 포함 X → Math.max(0, value)) + int left = Math.max(0, dfs(node.left)); + int right = Math.max(0, dfs(node.right)); + + // 현재 노드를 포함한 최대 경로 (왼쪽 + 루트 + 오른쪽) + int pathSum = left + node.val + right; + + // 최대 경로 값 갱신 + maxSum = Math.max(maxSum, pathSum); + + // ✅ 현재 노드를 포함하는 최대 경로 값만 반환해야 함 (연결 가능한 경로) + return node.val + Math.max(left, right); + } +} diff --git a/counting-bits/imsosleepy.java b/counting-bits/imsosleepy.java new file mode 100644 index 000000000..af00f93f0 --- /dev/null +++ b/counting-bits/imsosleepy.java @@ -0,0 +1,10 @@ +// Integer.bitCount(i)는 O(log n) 이걸림 그래서 n번 반복하면 O(nlogn) +public static int[] countBits(int n) { + int[] ans = new int[n + 1]; + + for (int i = 0; i <= n; i++) { + ans[i] = Integer.bitCount(i); + } + + return ans; +} diff --git a/house-robber-ii/imsosleepy.java b/house-robber-ii/imsosleepy.java new file mode 100644 index 000000000..d79819c5f --- /dev/null +++ b/house-robber-ii/imsosleepy.java @@ -0,0 +1,31 @@ +// house robber 1이 dp문제여서 dp문제라는거 알 수 있었음 +// 시작점을 다르게 해서 두개의 dp를 결합하는 아이디어는 맞았음(첫 집을 털었을때, 마지막 집을 털었을 때) +// 구현이 너무 오래걸려서 GPT의 도움을 받음.. +// DP는 아이디어가 절반이라 생각했는데 구현을 잘 못해서 아쉬움 +class Solution { + public int rob(int[] nums) { + if (nums.length == 1) return nums[0]; // 집이 하나면 그 집만 털면 됨. + + int n = nums.length; + + // 1. 첫 번째 집을 포함하지 않는 경우 (nums[1] ~ nums[n-1]) + int[] dp1 = new int[n]; + dp1[0] = 0; // 첫 번째 집을 포함하지 않으므로 0 + dp1[1] = nums[1]; // 두 번째 집을 털었을 경우 + + for (int i = 2; i < n; i++) { + dp1[i] = Math.max(dp1[i - 1], dp1[i - 2] + nums[i]); + } + + // 2. 마지막 집을 포함하지 않는 경우 (nums[0] ~ nums[n-2]) + int[] dp2 = new int[n]; + dp2[0] = nums[0]; // 첫 번째 집을 털었을 경우 + dp2[1] = Math.max(nums[0], nums[1]); // 두 번째 집을 털지 않을 수도 있음 + + for (int i = 2; i < n - 1; i++) { + dp2[i] = Math.max(dp2[i - 1], dp2[i - 2] + nums[i]); + } + + return Math.max(dp1[n - 1], dp2[n - 2]); + } +} diff --git a/meeting-rooms-ii/imsosleepy.java b/meeting-rooms-ii/imsosleepy.java new file mode 100644 index 000000000..151a08c7c --- /dev/null +++ b/meeting-rooms-ii/imsosleepy.java @@ -0,0 +1,30 @@ +// 정렬을 이용하면 O(nlogn)으로 풀리는데 다른 아이디어가 안떠오름 +class Solution { + public int minMeetingRooms(int[][] intervals) { + if (intervals == null || intervals.length == 0) return 0; + + int n = intervals.length; + int[] startTimes = new int[n]; + int[] endTimes = new int[n]; + + for (int i = 0; i < n; i++) { + startTimes[i] = intervals[i][0]; + endTimes[i] = intervals[i][1]; + } + + Arrays.sort(startTimes); + Arrays.sort(endTimes); + + int rooms = 0; + int endPointer = 0; + + for (int startPointer = 0; startPointer < n; startPointer++) { + if (startTimes[startPointer] < endTimes[endPointer]) { + rooms++; + endPointer++; + } + } + + return rooms; + } +} diff --git a/word-search-ii/imsosleepy.java b/word-search-ii/imsosleepy.java new file mode 100644 index 000000000..46adbfc94 --- /dev/null +++ b/word-search-ii/imsosleepy.java @@ -0,0 +1,68 @@ +// 모든 위치에서 DFS를 실행 or BFS를 돌면서 단어 찾는 경우 모든 경우에 타임아웃이 발생 +// 도저히 해결을 못할거 같아서 GPT의 도움을 받음 +// Trie를 이용했는데 조금 더 고민해봐야할 듯 +class TrieNode { + Map children = new HashMap<>(); + String word = null; +} + +class Solution { + public List findWords(char[][] board, String[] words) { + List result = new ArrayList<>(); + TrieNode root = buildTrie(words); + + for (int i = 0; i < board.length; i++) { + for (int j = 0; j < board[0].length; j++) { + dfs(board, i, j, root, result); + } + } + return result; + } + + // Trie(트라이) 자료구조를 구축 + private TrieNode buildTrie(String[] words) { + TrieNode root = new TrieNode(); + for (String word : words) { + TrieNode node = root; + for (char c : word.toCharArray()) { + node.children.putIfAbsent(c, new TrieNode()); + node = node.children.get(c); + } + node.word = word; + } + return root; + } + + // DFS + 백트래킹 탐색 + private void dfs(char[][] board, int i, int j, TrieNode node, List result) { + char c = board[i][j]; + if (!node.children.containsKey(c)) return; // 현재 문자와 일치하는 것이 Trie에 없으면 종료 + + TrieNode nextNode = node.children.get(c); + if (nextNode.word != null) { // 단어를 찾았으면 결과 리스트에 추가 + result.add(nextNode.word); + nextNode.word = null; // 중복 방지를 위해 제거 + } + + // 방문 표시 (백트래킹을 위해) + board[i][j] = '#'; + + // 4방향 탐색 + int[] dx = {-1, 1, 0, 0}; + int[] dy = {0, 0, -1, 1}; + for (int d = 0; d < 4; d++) { + int x = i + dx[d], y = j + dy[d]; + if (x >= 0 && x < board.length && y >= 0 && y < board[0].length) { + dfs(board, x, y, nextNode, result); + } + } + + // 백트래킹 (원래 문자로 복원) + board[i][j] = c; + + // **최적화**: 더 이상 자식이 없으면 Trie에서 해당 노드 삭제 + if (nextNode.children.isEmpty()) { + node.children.remove(c); + } + } +}