Skip to content

Commit 13ba8ba

Browse files
authored
Merge pull request #1033 from EcoFriendlyAppleSu/main
[친환경사과] Week 11
2 parents 3887c3b + 3800d3c commit 13ba8ba

File tree

3 files changed

+149
-0
lines changed

3 files changed

+149
-0
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package leetcode_study
2+
3+
/*
4+
* 이진 트리의 최대 깊이를 구하는 문제
5+
* 재귀를 사용해 문제 해결
6+
* 시간 복잡도: O(n)
7+
* -> 이진 트리의 모든 노드를 방문
8+
* 공간 복잡도: O(n) 혹은 O(log n)
9+
* -> findDepth() 함수는 재귀적으로 호출되어 콜 스택에 쌓임
10+
* -> 균형잡힌 이진트리의 경우 재귀의 깊이는 O(log n) 소요
11+
* -> 편향된 이진트리의 경우 재귀의 깊이는 O(n) 소요
12+
* */
13+
fun maxDepth(root: TreeNode?): Int {
14+
if (root == null) return 0
15+
val maxValue = findDepth(root, 1) // 시작 깊이 값은 `1`
16+
return maxValue
17+
}
18+
19+
fun findDepth(currentNode: TreeNode?, depth: Int): Int{
20+
// escape condition
21+
if (currentNode == null) {
22+
return depth - 1
23+
}
24+
25+
val leftValue = findDepth(currentNode.left, depth + 1)
26+
val rightValue = findDepth(currentNode.right, depth + 1)
27+
return maxOf(leftValue, rightValue)
28+
}

merge-intervals/EcoFriendlyAppleSu.kt

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package leetcode_study
2+
3+
/*
4+
* 주어진 범위 값 병합 문제
5+
* */
6+
7+
/*
8+
* 첫 번째 풀이. 틀림
9+
* 범위 안에 속하는 모든 값을 Set 자료구조에 넣고 제일 큰 숫자 만큼의 Boolean Array를 만든 후 방문처리하는 방식으로 접근
10+
* 예외 케이스
11+
* intervals = [[1,4],[5,6]] 일 때,
12+
* 연속된 값으로 인식해 답을 [[1,6]]로 도출. 올바른 답은 [[1,4],[5,6]]
13+
* */
14+
fun merge01(intervals: Array<IntArray>): Array<IntArray> {
15+
val tempSet = mutableSetOf<Int>()
16+
var maxValue = Int.MIN_VALUE
17+
18+
for (interval in intervals) {
19+
val leftValue = interval[0]
20+
val rightValue = interval[1]
21+
maxValue = max(maxValue, rightValue)
22+
for (value in leftValue until rightValue + 1) {
23+
tempSet.add(value)
24+
}
25+
}
26+
27+
val checkVisited = BooleanArray(maxValue + 1) { false }
28+
for (value in tempSet) {
29+
checkVisited[value] = true
30+
}
31+
32+
val result = mutableListOf<IntArray>()
33+
var start: Int? = null
34+
35+
for (i in checkVisited.indices) {
36+
if (checkVisited[i]) {
37+
if (start == null) start = i // 시작점 저장
38+
// 연속된 값이 true일 경우엔 넘어감
39+
} else {
40+
if (start != null) {
41+
result.add(intArrayOf(start, i - 1)) // [start, end] 추가
42+
start = null
43+
}
44+
}
45+
}
46+
if (start != null) {
47+
result.add(intArrayOf(start, checkVisited.lastIndex))
48+
}
49+
50+
return result.toTypedArray()
51+
}
52+
53+
/*
54+
* 주어진 범위 값을 정렬하고 순회하면서 병합 여부 판단
55+
* 시간 복잡도: O(n log n)
56+
* -> 첫 번째 원소 기준으로 TimSort 알고리즘을 사용한 정렬: O(n log n)
57+
* -> 주어진 interval 만큼 순회해 계산: O(n)
58+
* 공간 복잡도: O(n)
59+
* -> 첫 번째 원소로 정렬된 sortedIntervals를 담는 공간: O(n)
60+
* */
61+
fun merge02(intervals: Array<IntArray>): Array<IntArray> {
62+
if (intervals.isEmpty()) return intervals
63+
64+
// 시작점 기준으로 정렬
65+
val sortedIntervals = intervals.sortedBy { it[0] }
66+
67+
val result = mutableListOf<IntArray>()
68+
var currentInterval = sortedIntervals[0]
69+
70+
for (i in 1 until sortedIntervals.size) {
71+
val interval = sortedIntervals[i]
72+
// 겹치는 경우: 현재 구간의 끝이 다음 구간의 시작보다 크거나 같으면 merge
73+
if (currentInterval[1] >= interval[0]) {
74+
currentInterval[1] = maxOf(currentInterval[1], interval[1])
75+
} else {
76+
// 겹치지 않으면 현재 구간을 결과에 추가하고, 새 구간으로 변경
77+
result.add(currentInterval)
78+
currentInterval = interval
79+
}
80+
}
81+
// 마지막 구간 추가
82+
result.add(currentInterval)
83+
84+
return result.toTypedArray()
85+
}

reorder-list/EcoFriendlyAppleSu.kt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package leetcode_study
2+
3+
/*
4+
* singly linked list를 재정렬하는 문제
5+
* 시간 복잡도: O(n)
6+
* -> 전체 노드를 저장하기 위해 순환하는 과정 O(n)
7+
* -> 리스트의 앞과 뒤에 포인터를 두고 주소값을 변경하는 과정 O(log n)
8+
* 공간 복잡도: O(n)
9+
* -> 노드 전체를 담을 새로운 list 필요 O(n)
10+
* */
11+
fun reorderList(head: ListNode?): Unit {
12+
val tempNodeList = mutableListOf<ListNode>()
13+
var currentNode = head
14+
15+
while (currentNode != null) {
16+
tempNodeList.add(currentNode)
17+
currentNode = currentNode.next
18+
}
19+
20+
// 양쪽 끝에서부터 교차로 연결
21+
var i = 0
22+
var j = tempNodeList.size - 1
23+
while (i < j) {
24+
// 먼저 앞쪽 노드의 next가 뒤쪽 노드를 가리키게 함
25+
tempNodeList[i].next = tempNodeList[j]
26+
i++ // 다음 앞쪽 노드 선택
27+
28+
// 만약 앞쪽과 뒤쪽이 만난 경우 (짝수개일 때), 반복 종료
29+
if (i == j) break
30+
31+
// 뒤쪽 노드의 next가 새로운 앞쪽 노드를 가리키게 함
32+
tempNodeList[j].next = tempNodeList[i]
33+
j-- // 다음 뒤쪽 노드 선택
34+
}
35+
tempNodeList[i].next = null
36+
}

0 commit comments

Comments
 (0)