diff --git a/course-schedule/jaejeong1.kt b/course-schedule/jaejeong1.kt new file mode 100644 index 0000000000..1a6ca7da16 --- /dev/null +++ b/course-schedule/jaejeong1.kt @@ -0,0 +1,47 @@ +import java.util.LinkedList +import java.util.Queue + +class `Course-Schedule` { + fun canFinish(numCourses: Int, prerequisites: Array): Boolean { + // 시간복잡도: O(N), 공간복잡도: O(N) + + // 그래프와 선이수 과목 개수 배열 초기화 + val adj = Array(numCourses) { mutableListOf() } + val indegree = IntArray(numCourses) + + // 데이터 채우기 (preCourse 를 들어야 course 를 들을 수 있음) + // indegree[course] 는 course 를 듣기 위한 선이수 과목 개수 + for (pre in prerequisites) { + val course = pre[0] + val preCourse = pre[1] + + adj[preCourse].add(course) + indegree[course]++ + } + + // 선이수 과목 개수가 0인 과목을 큐에 추가 + val queue: Queue = LinkedList() + for (i in 0 until numCourses) { + if (indegree[i] == 0) { + queue.offer(i) + } + } + + var completedCourses = 0 + + while (queue.isNotEmpty()) { + val current = queue.poll() + completedCourses++ + // 완료한 과목을 선이수 과목으로 갖는 과목들의 선이수 과목 개수를 차감 + for (nextCourse in adj[current]) { + indegree[nextCourse]-- + // 선이수 과목 개수가 0이 되면 큐에 추가 + if (indegree[nextCourse] == 0) { + queue.offer(nextCourse) + } + } + } + // 완료한 과목 개수와 입력 과목 개수가 같은지 + return completedCourses == numCourses + } +} diff --git a/invert-binary-tree/jaejeong1.kt b/invert-binary-tree/jaejeong1.kt new file mode 100644 index 0000000000..23ca0bcb9a --- /dev/null +++ b/invert-binary-tree/jaejeong1.kt @@ -0,0 +1,27 @@ +class TreeNode(var `val`: Int) { + var left: TreeNode? = null + var right: TreeNode? = null +} + +class InvertBinaryTree { + fun invertTree(root: TreeNode?): TreeNode? { + // 이진 트리의 root 를 주면, 트리를 뒤집고, 그것의 Root를 반환해라 + // 재귀적으로 left, right 를 바꾸면 된다. child가 둘다 null 이면 종료 + // 시간복잡도: O(N), 공간복잡도: O(1) + if (root == null) return null + + if (root.left == null && root.right == null) { + return root + } + + val temp = root.left + root.left = root.right + root.right = temp + + invertTree(root.left) + invertTree(root.right) + + return root + } + +} diff --git a/search-in-rotated-sorted-array/jaejeong1.kt b/search-in-rotated-sorted-array/jaejeong1.kt new file mode 100644 index 0000000000..ca4e647797 --- /dev/null +++ b/search-in-rotated-sorted-array/jaejeong1.kt @@ -0,0 +1,64 @@ +class `Search-in-Rotated-Sorted-Array` { + fun search(nums: IntArray, target: Int): Int { + // log n -> 이진 탐색 + // 이진 탐색 -> 왼쪽은 작고, 오른쪽은 크다 + // 그렇다면.. 회전된 인덱스 기준으로 잘라서 좌우에서 각각 이진 탐색하면 가능하다 + // 회전된 인덱스 어떻게 찾나? -> 이진 탐색해서 좌측이 더 크거나, 우측이 더 작으면 우측이 인덱스다 + + // 1단계: 이진 탐색해서 회전한 인덱스 찾기 + // 2단계: 회전한 인덱스 기준으로 좌우 자르고, 각각 이진 탐색하기 + // 3단계: 둘다 없으면 -1, 좌측 또는 우측에서 답 찾아서 반환 + // 시간복잡도: O(log n), 공간복잡도: O(1) + + val rotatedIndex = findRotatedIndex(nums) + val index = binarySearch(nums, 0, rotatedIndex - 1, target) + // 왼쪽에 답이 있는지 + if (index > -1) { + return index + } + // 없으면 오른쪽 답 탐색해서 반환 + return binarySearch(nums, rotatedIndex, nums.size - 1, target) + } + + fun findRotatedIndex(nums: IntArray): Int { + // nums[0] 이 nums[mid]보다 크면 rotated index 는 왼쪽에 있음 + // 정렬되어있다면 위 조건이 될 수 없기 때문 + var left = 0 + var right = nums.size - 1 + while (left <= right) { + val mid = left + (right - left) / 2 + // 좌측 값이 더 크면 rotated index + if (0 < mid && nums[mid - 1] > nums[mid]) { + return mid + } + // 왼쪽이 정렬되었는지 + if (nums[0] <= nums[mid]) { + left = mid + 1 + } + // 오른쪽이 정렬되었는지 + else { + right = mid - 1 + } + } + return 0 + } + + fun binarySearch(nums: IntArray, left: Int, right: Int, target: Int): Int { + var left = left + var right = right + + while (left <= right) { + val mid = left + (right - left) / 2 + if (nums[mid] == target) { + return mid + } + if (nums[mid] < target) { + left = mid + 1 + } + else { + right = mid - 1 + } + } + return -1 + } +}