diff --git a/course-schedule/imsosleepy.java b/course-schedule/imsosleepy.java new file mode 100644 index 000000000..86301c96b --- /dev/null +++ b/course-schedule/imsosleepy.java @@ -0,0 +1,40 @@ +// 사이클을 찾는 문제. DFS를 이용해서 방문했는지 여부를 관리하고 체크하면된다. +// DFS를 진행 중인 것을 들고 있어야 사이클 여부를 판단할 수 있다. +// 간선 수와 노드의 수에 따라 시간 복잡도가 결정됨 O(N+L) +class Solution { + public boolean canFinish(int numCourses, int[][] prerequisites) { + List> graph = new ArrayList<>(); + for (int i = 0; i < numCourses; i++) { + graph.add(new ArrayList<>()); + } + + for (int[] pair : prerequisites) { + graph.get(pair[1]).add(pair[0]); + } + + // 0: 방문 X + // -1: DFS 진행 중 + // 1: 방문 완료 + int[] visited = new int[numCourses]; + + // 모든 노드에서 DFS 수행 + for (int i = 0; i < numCourses; i++) { + if (dfs(graph, visited, i)) return false; + } + + return true; + } + + private boolean dfs(List> graph, int[] visited, int node) { + if (visited[node] == -1) return true; // 방문 중이면 사이클이 발견 + if (visited[node] == 1) return false; + + visited[node] = -1; // 진행 중 표기 + for (int next : graph.get(node)) { + if (dfs(graph, visited, next)) return true; + } + visited[node] = 1; + + return false; + } +} diff --git a/invert-binary-tree/imsosleepy.java b/invert-binary-tree/imsosleepy.java new file mode 100644 index 000000000..80ecbeb7a --- /dev/null +++ b/invert-binary-tree/imsosleepy.java @@ -0,0 +1,13 @@ +// 트리의 형태를 바꾸는건 대부분 DFS로 푸는게 공간복잡도 측면에서 유리하다. +// BFS로도 풀이 가능하지만, BFS는 대부분 큐를 이용해서 공간복잡도가 높아진다. +class Solution { + public TreeNode invertTree(TreeNode root) { + if (root == null) return null; + + TreeNode temp = root.left; + root.left = invertTree(root.right); + root.right = invertTree(temp); + + return root; + } +} diff --git a/jump-game/imsosleepy.java b/jump-game/imsosleepy.java new file mode 100644 index 000000000..dd681c90b --- /dev/null +++ b/jump-game/imsosleepy.java @@ -0,0 +1,20 @@ +// 현재 위치에서 최대로 갈 수 있는 인덱스의 이력을 갱신하면서 최대 범위를 넘지 않았나를 계속 판별하면 됨 +// 처음엔 DP인줄 알았는데 DP 배열 없이 그냥 풀림 +class Solution { + public boolean canJump(int[] nums) { + int maxReach = 0; + + for (int i = 0; i < nums.length; i++) { + if (i > maxReach) { + return false; + } + + maxReach = Math.max(maxReach, i + nums[i]); + if (maxReach >= nums.length - 1) { + return true; + } + } + + return true; + } +} diff --git a/merge-k-sorted-lists/imsosleepy.java b/merge-k-sorted-lists/imsosleepy.java new file mode 100644 index 000000000..bdd277801 --- /dev/null +++ b/merge-k-sorted-lists/imsosleepy.java @@ -0,0 +1,27 @@ +// 우선순위 큐로 다 합쳐버린 다음에 +// 큐를 순회돌면서 연결리스트를 재생성한다. 성능은 비교적 낮게 잡힘 +// 분할 정복법으로 풀면 더 좋은 성능이 나온다고 한다. +class Solution { + public ListNode mergeKLists(ListNode[] lists) { + PriorityQueue pq = new PriorityQueue<>((a, b) -> a.val - b.val); + + for (ListNode node : lists) { + if (node != null) pq.offer(node); + } + + ListNode newLists = new ListNode(-1); + ListNode curr = newLists; + + while (!pq.isEmpty()) { + ListNode minNode = pq.poll(); + curr.next = minNode; + curr = curr.next; + + if (minNode.next != null) { + pq.offer(minNode.next); + } + } + + return newLists.next; + } +} diff --git a/search-in-rotated-sorted-array/imsosleepy.java b/search-in-rotated-sorted-array/imsosleepy.java new file mode 100644 index 000000000..fdcab5225 --- /dev/null +++ b/search-in-rotated-sorted-array/imsosleepy.java @@ -0,0 +1,35 @@ +// O(log n)의 시간복잡도를 문제에서 요구하고 있다. +// O(log n)의 시간복잡도를 갖는 탐색 문제는 대부분 바이너리 서치로 해결된다. +// 주어진 배열이 정렬되어있다는 점에서 이진탐색을 이용하면 된다는 것을 알 수 있다. +class Solution { + public int search(int[] nums, int target) { + int left = 0, right = nums.length - 1; + + while (left <= right) { + int mid = left + (right - left) / 2; + + if (nums[mid] == target) { + return mid; + } + + // 왼쪽이 정렬된 경우 + if (nums[left] <= nums[mid]) { + if (nums[left] <= target && target < nums[mid]) { + right = mid - 1; + } else { + left = mid + 1; + } + } + // 오른쪽이 정렬된 경우 + else { + if (nums[mid] < target && target <= nums[right]) { + left = mid + 1; + } else { + right = mid - 1; + } + } + } + + return -1; + } +}