diff --git a/maximum-depth-of-binary-tree/EcoFriendlyAppleSu.kt b/maximum-depth-of-binary-tree/EcoFriendlyAppleSu.kt new file mode 100644 index 000000000..5118ef05e --- /dev/null +++ b/maximum-depth-of-binary-tree/EcoFriendlyAppleSu.kt @@ -0,0 +1,28 @@ +package leetcode_study + +/* +* 이진 트리의 최대 깊이를 구하는 문제 +* 재귀를 사용해 문제 해결 +* 시간 복잡도: O(n) +* -> 이진 트리의 모든 노드를 방문 +* 공간 복잡도: O(n) 혹은 O(log n) +* -> findDepth() 함수는 재귀적으로 호출되어 콜 스택에 쌓임 +* -> 균형잡힌 이진트리의 경우 재귀의 깊이는 O(log n) 소요 +* -> 편향된 이진트리의 경우 재귀의 깊이는 O(n) 소요 +* */ +fun maxDepth(root: TreeNode?): Int { + if (root == null) return 0 + val maxValue = findDepth(root, 1) // 시작 깊이 값은 `1` + return maxValue +} + +fun findDepth(currentNode: TreeNode?, depth: Int): Int{ + // escape condition + if (currentNode == null) { + return depth - 1 + } + + val leftValue = findDepth(currentNode.left, depth + 1) + val rightValue = findDepth(currentNode.right, depth + 1) + return maxOf(leftValue, rightValue) +} diff --git a/merge-intervals/EcoFriendlyAppleSu.kt b/merge-intervals/EcoFriendlyAppleSu.kt new file mode 100644 index 000000000..2492053d8 --- /dev/null +++ b/merge-intervals/EcoFriendlyAppleSu.kt @@ -0,0 +1,85 @@ +package leetcode_study + +/* +* 주어진 범위 값 병합 문제 +* */ + +/* +* 첫 번째 풀이. 틀림 +* 범위 안에 속하는 모든 값을 Set 자료구조에 넣고 제일 큰 숫자 만큼의 Boolean Array를 만든 후 방문처리하는 방식으로 접근 +* 예외 케이스 +* intervals = [[1,4],[5,6]] 일 때, +* 연속된 값으로 인식해 답을 [[1,6]]로 도출. 올바른 답은 [[1,4],[5,6]] +* */ +fun merge01(intervals: Array): Array { + val tempSet = mutableSetOf() + var maxValue = Int.MIN_VALUE + + for (interval in intervals) { + val leftValue = interval[0] + val rightValue = interval[1] + maxValue = max(maxValue, rightValue) + for (value in leftValue until rightValue + 1) { + tempSet.add(value) + } + } + + val checkVisited = BooleanArray(maxValue + 1) { false } + for (value in tempSet) { + checkVisited[value] = true + } + + val result = mutableListOf() + var start: Int? = null + + for (i in checkVisited.indices) { + if (checkVisited[i]) { + if (start == null) start = i // 시작점 저장 + // 연속된 값이 true일 경우엔 넘어감 + } else { + if (start != null) { + result.add(intArrayOf(start, i - 1)) // [start, end] 추가 + start = null + } + } + } + if (start != null) { + result.add(intArrayOf(start, checkVisited.lastIndex)) + } + + return result.toTypedArray() +} + +/* +* 주어진 범위 값을 정렬하고 순회하면서 병합 여부 판단 +* 시간 복잡도: O(n log n) +* -> 첫 번째 원소 기준으로 TimSort 알고리즘을 사용한 정렬: O(n log n) +* -> 주어진 interval 만큼 순회해 계산: O(n) +* 공간 복잡도: O(n) +* -> 첫 번째 원소로 정렬된 sortedIntervals를 담는 공간: O(n) +* */ +fun merge02(intervals: Array): Array { + if (intervals.isEmpty()) return intervals + + // 시작점 기준으로 정렬 + val sortedIntervals = intervals.sortedBy { it[0] } + + val result = mutableListOf() + var currentInterval = sortedIntervals[0] + + for (i in 1 until sortedIntervals.size) { + val interval = sortedIntervals[i] + // 겹치는 경우: 현재 구간의 끝이 다음 구간의 시작보다 크거나 같으면 merge + if (currentInterval[1] >= interval[0]) { + currentInterval[1] = maxOf(currentInterval[1], interval[1]) + } else { + // 겹치지 않으면 현재 구간을 결과에 추가하고, 새 구간으로 변경 + result.add(currentInterval) + currentInterval = interval + } + } + // 마지막 구간 추가 + result.add(currentInterval) + + return result.toTypedArray() +} diff --git a/reorder-list/EcoFriendlyAppleSu.kt b/reorder-list/EcoFriendlyAppleSu.kt new file mode 100644 index 000000000..8ed6dd0e3 --- /dev/null +++ b/reorder-list/EcoFriendlyAppleSu.kt @@ -0,0 +1,36 @@ +package leetcode_study + +/* +* singly linked list를 재정렬하는 문제 +* 시간 복잡도: O(n) +* -> 전체 노드를 저장하기 위해 순환하는 과정 O(n) +* -> 리스트의 앞과 뒤에 포인터를 두고 주소값을 변경하는 과정 O(log n) +* 공간 복잡도: O(n) +* -> 노드 전체를 담을 새로운 list 필요 O(n) +* */ +fun reorderList(head: ListNode?): Unit { + val tempNodeList = mutableListOf() + var currentNode = head + + while (currentNode != null) { + tempNodeList.add(currentNode) + currentNode = currentNode.next + } + + // 양쪽 끝에서부터 교차로 연결 + var i = 0 + var j = tempNodeList.size - 1 + while (i < j) { + // 먼저 앞쪽 노드의 next가 뒤쪽 노드를 가리키게 함 + tempNodeList[i].next = tempNodeList[j] + i++ // 다음 앞쪽 노드 선택 + + // 만약 앞쪽과 뒤쪽이 만난 경우 (짝수개일 때), 반복 종료 + if (i == j) break + + // 뒤쪽 노드의 next가 새로운 앞쪽 노드를 가리키게 함 + tempNodeList[j].next = tempNodeList[i] + j-- // 다음 뒤쪽 노드 선택 + } + tempNodeList[i].next = null +}