diff --git a/binary-tree-level-order-traversal/imsosleepy.java b/binary-tree-level-order-traversal/imsosleepy.java new file mode 100644 index 000000000..c94b68ee4 --- /dev/null +++ b/binary-tree-level-order-traversal/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/graph-valid-tree/imsosleepy.java b/graph-valid-tree/imsosleepy.java new file mode 100644 index 000000000..8504bcb6b --- /dev/null +++ b/graph-valid-tree/imsosleepy.java @@ -0,0 +1,34 @@ +// 저번주 course-schedule 문제와 유사한 사이클이 존재하지 않아야하는 트리를 찾는 문제 +// 차이가 있다면 course-schedule는 방향 그래프지만 이 문제는 무방향 그래프라는 차이가 있음 +// 무방향 그래프는 이전 노드(부모)를 통해 다시 돌아온 후 연결을 판단해야하는 경우가 있어거 구현이 조금 더 어려움 +public class GraphValidTree { + public boolean validTree(int n, int[][] edges) { + if (edges.length != n - 1) return false; // 트리는 반드시 (n-1)개의 간선 필요 + + // 그래프 인접 리스트 생성 + Map> graph = new HashMap<>(); + for (int i = 0; i < n; i++) { + graph.put(i, new ArrayList<>()); + } + for (int[] edge : edges) { + graph.get(edge[0]).add(edge[1]); + graph.get(edge[1]).add(edge[0]); + } + + Set visited = new HashSet<>(); + if (!dfs(graph, 0, -1, visited)) return false; + + return visited.size() == n; + } + + private boolean dfs(Map> graph, int node, int parent, Set visited) { + if (visited.contains(node)) return false; // 사이클 발견 + + visited.add(node); + for (int neighbor : graph.get(node)) { + if (neighbor == parent) continue; + if (!dfs(graph, neighbor, node, visited)) return false; + } + return true; + } +} diff --git a/maximum-depth-of-binary-tree/imsosleepy.java b/maximum-depth-of-binary-tree/imsosleepy.java new file mode 100644 index 000000000..3bc9f497b --- /dev/null +++ b/maximum-depth-of-binary-tree/imsosleepy.java @@ -0,0 +1,8 @@ +// 트리 탐색은 깊이 우선 탐색이 공간복잡도가 낮다. +// 모든 노드(리스트)를 O(N)의 시간복잡도를 갖는다. +class Solution { + public int maxDepth(TreeNode root) { + if (root == null) return 0; + return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1; + } +} diff --git a/merge-intervals/imsosleepy.java b/merge-intervals/imsosleepy.java new file mode 100644 index 000000000..ff292e352 --- /dev/null +++ b/merge-intervals/imsosleepy.java @@ -0,0 +1,31 @@ +// 정렬을 하지 않으려면 O(N^2)이 걸림 +// 정렬을 나면 아무리 빨라도 O(N log N)이지만 이후에 문제가 간단해짐 +// currentEnd >= nextStart → 겹치면 end 값을 업데이트 하는 간단한 방식으로 구현 +class Solution { + public int[][] merge(int[][] intervals) { + if (intervals.length <= 1) return intervals; + + Arrays.sort(intervals, (a, b) -> Integer.compare(a[0], b[0])); + + List merged = new ArrayList<>(); + int[] currentInterval = intervals[0]; + merged.add(currentInterval); + + for (int[] interval : intervals) { + int currentEnd = currentInterval[1]; + int nextStart = interval[0]; + int nextEnd = interval[1]; + + if (currentEnd >= nextStart) { + // 겹치면 end 값을 업데이트 + currentInterval[1] = Math.max(currentEnd, nextEnd); + } else { + // 겹치지 않으면 새로운 구간으로 추가 + currentInterval = interval; + merged.add(currentInterval); + } + } + + return merged.toArray(new int[merged.size()][]); + } +} diff --git a/reorder-list/imsosleepy.java b/reorder-list/imsosleepy.java new file mode 100644 index 000000000..167aed78d --- /dev/null +++ b/reorder-list/imsosleepy.java @@ -0,0 +1,63 @@ +// GPT의 도움을 받아 조금 더 공간복잡도가 낮고 빠른 방식으로 구현 +class Solution { + public void reorderList(ListNode head) { + if (head == null || head.next == null) return; + + ListNode slow = head, fast = head; + while (fast != null && fast.next != null) { + slow = slow.next; + fast = fast.next.next; + } + + ListNode second = reverse(slow.next); + slow.next = null; + + ListNode first = head; + while (second != null) { + ListNode tmp1 = first.next; + ListNode tmp2 = second.next; + + first.next = second; + second.next = tmp1; + + first = tmp1; + second = tmp2; + } + } + + private ListNode reverse(ListNode head) { + ListNode prev = null; + while (head != null) { + ListNode next = head.next; + head.next = prev; + prev = head; + head = next; + } + return prev; + } +} + +// 첫번째 생각한 풀이방식 리스트를 만들고 값을 넣어서 처리하니 시간복잡도는 O(N)으로 이론상 같으나 +// 속도라 평균속도보다 현저하게 낮게나온다. +class Solution { + public void reorderList(ListNode head) { + if (head == null || head.next == null) return; + + List list = new ArrayList<>(); + ListNode temp = head; + while (temp != null) { + list.add(temp); + temp = temp.next; + } + + int i = 0, j = list.size() - 1; + while (i < j) { + list.get(i).next = list.get(j); + i++; + if (i == j) break; + list.get(j).next = list.get(i); + j--; + } + list.get(i).next = null; + } +}