Skip to content

Commit 212bfe6

Browse files
authored
Merge pull request #549 from jdalma/main
[정현준] 11주차
2 parents 34452e9 + 3dc9850 commit 212bfe6

File tree

5 files changed

+275
-0
lines changed

5 files changed

+275
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.shouldBe
4+
import org.junit.jupiter.api.Test
5+
import kotlin.math.max
6+
7+
class `binary-tree-maximum-path-sum` {
8+
9+
/**
10+
* TC: O(n), SC: O(log n)
11+
*/
12+
fun maxPathSum(root: TreeNode?): Int {
13+
if (root == null) return 0
14+
var max = root.`val` // 부모 노드와 2개의 자식 노드의 합을 전역 변수로 갱신한다.
15+
16+
fun dfs(node: TreeNode?): Int {
17+
if (node == null) return 0
18+
19+
val left = max(dfs(node.left), 0)
20+
val right = max(dfs(node.right), 0)
21+
22+
max = max(node.`val` + left + right, max)
23+
return node.`val` + max(left, right) // 현재 노드와 2개의 자식 노드 중 최대의 값을 반환한다.
24+
}
25+
26+
dfs(root)
27+
return max
28+
}
29+
30+
@Test
31+
fun `이진 트리의 최대 경로 합을 반환한다`() {
32+
maxPathSum(TreeNode.of(-10,9,20,null,null,15,7)) shouldBe 42
33+
maxPathSum(TreeNode.of(1,9,20,null,null,15,7)) shouldBe 45
34+
}
35+
}

graph-valid-tree/jdalma.kt

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.shouldBe
4+
import org.junit.jupiter.api.Test
5+
6+
class `graph-valid-tree` {
7+
8+
/**
9+
* TC: O(n), SC: O(n)
10+
*/
11+
fun validTree(nodeSize: Int, edges: Array<IntArray>): Boolean {
12+
if (nodeSize - 1 != edges.size) {
13+
return false
14+
}
15+
16+
val visited = mutableSetOf<Int>()
17+
val adj = List(nodeSize) { mutableListOf<Int>() }
18+
for (e in edges) {
19+
adj[e[0]].add(e[1])
20+
adj[e[1]].add(e[0])
21+
}
22+
23+
val queue = ArrayDeque<Int>().apply {
24+
this.add(0)
25+
}
26+
27+
while (queue.isNotEmpty()) {
28+
val now = queue.removeFirst()
29+
visited.add(now)
30+
for (next in adj[now]) {
31+
if (!visited.contains(next)) {
32+
queue.add(next)
33+
}
34+
}
35+
}
36+
37+
return nodeSize == visited.size
38+
}
39+
40+
@Test
41+
fun `노드가 트리의 조건을 만족하는지 여부를 반환한다`() {
42+
validTree(5,
43+
arrayOf(
44+
intArrayOf(0,1),
45+
intArrayOf(0,2),
46+
intArrayOf(0,3),
47+
intArrayOf(1,4)
48+
)
49+
) shouldBe true
50+
51+
validTree(5,
52+
arrayOf(
53+
intArrayOf(0,1),
54+
intArrayOf(0,2),
55+
intArrayOf(0,3),
56+
intArrayOf(1,4),
57+
intArrayOf(2,3),
58+
)
59+
) shouldBe false
60+
}
61+
}

insert-interval/jdalma.kt

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.shouldBe
4+
import org.junit.jupiter.api.Test
5+
import kotlin.math.max
6+
import kotlin.math.min
7+
8+
class `insert-interval` {
9+
10+
/**
11+
* TC: O(n), SC: O(n)
12+
*/
13+
fun insert(intervals: Array<IntArray>, newInterval: IntArray): Array<IntArray> {
14+
if (intervals.isEmpty()) return arrayOf(newInterval)
15+
return justIterate(intervals, newInterval)
16+
}
17+
18+
private fun justIterate(intervals: Array<IntArray>, newInterval: IntArray): Array<IntArray> {
19+
val result = mutableListOf<IntArray>()
20+
var new: IntArray? = newInterval
21+
22+
for (interval in intervals) {
23+
if (new != null) {
24+
if (new[1] < interval[0]) {
25+
// new 범위가 더 앞에 있다
26+
result.add(new)
27+
result.add(interval)
28+
new = null
29+
} else if (new[0] > interval[1]) {
30+
// new 범위가 더 뒤에 있어 다른 범위에 포함될 가능성이 있음
31+
result.add(interval)
32+
} else {
33+
new[0] = min(new[0], interval[0])
34+
new[1] = max(new[1], interval[1])
35+
}
36+
} else {
37+
result.add(interval)
38+
}
39+
}
40+
if (new != null) {
41+
result.add(new)
42+
}
43+
return result.toTypedArray()
44+
}
45+
46+
@Test
47+
fun name() {
48+
insert(
49+
arrayOf(
50+
intArrayOf(1,2),
51+
intArrayOf(3,5),
52+
intArrayOf(6,7),
53+
intArrayOf(8,10),
54+
intArrayOf(12,16)
55+
),
56+
intArrayOf(4,8)
57+
) shouldBe arrayOf(intArrayOf(1,2), intArrayOf(3,10), intArrayOf(12,16))
58+
}
59+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.shouldBe
4+
import org.junit.jupiter.api.Test
5+
import kotlin.math.max
6+
7+
class `maximum-depth-of-binary-tree` {
8+
9+
/**
10+
* 이진 트리이기에 스택의 깊이가 차지하는 공간 복잡도는 log일 것
11+
* TC: O(n), SC: O(log n)
12+
*/
13+
fun maxDepth(root: TreeNode?): Int {
14+
return if (root == null) 0
15+
else max(maxDepth(root.left) + 1, maxDepth(root.right) + 1)
16+
}
17+
18+
@Test
19+
fun `노드의 최대 깊이를 반환한다`() {
20+
maxDepth(TreeNode.of(3,9,20,null,null,15,7)) shouldBe 3
21+
}
22+
}

reorder-list/jdalma.kt

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.shouldBe
4+
import org.junit.jupiter.api.Test
5+
6+
class `reorder-list` {
7+
8+
fun reorderList(root: ListNode?) {
9+
if (root == null) return
10+
usingTwoPointers(root)
11+
}
12+
13+
/**
14+
* TC: O(n), SC: O(n)
15+
*/
16+
private fun usingStack(input: ListNode) {
17+
val tail = ArrayDeque<ListNode>().apply {
18+
var node: ListNode? = input
19+
while (node != null) {
20+
this.add(node)
21+
node = node.next
22+
}
23+
}
24+
25+
val dummy = ListNode(-1)
26+
var node: ListNode = dummy
27+
var head: ListNode = input
28+
for (i in 0 until tail.size) {
29+
if (i % 2 != 0) {
30+
node.next = tail.removeLast()
31+
} else {
32+
node.next = head
33+
head.next?.let { head = it }
34+
}
35+
node.next?.let { node = it }
36+
}
37+
node.next = null
38+
}
39+
40+
/**
41+
* TC: O(n), SC: O(1)
42+
*/
43+
private fun usingTwoPointers(input: ListNode) {
44+
if (input.next == null) return
45+
46+
var slow: ListNode? = input
47+
var fast: ListNode? = input
48+
while (fast?.next != null && fast.next?.next != null) {
49+
slow = slow?.next
50+
fast = fast.next?.next
51+
}
52+
53+
val firstHalfEnd = slow
54+
var secondHalfStart = slow?.next
55+
firstHalfEnd?.next = null
56+
57+
secondHalfStart = reverse(secondHalfStart)
58+
59+
var node1: ListNode? = input
60+
var node2: ListNode? = secondHalfStart
61+
while (node2 != null) {
62+
val (next1, next2) = (node1?.next to node2?.next)
63+
node1?.next = node2
64+
node2.next = next1
65+
node1 = next1
66+
node2 = next2
67+
}
68+
}
69+
70+
private fun reverse(head: ListNode?): ListNode? {
71+
var prev: ListNode? = null
72+
var current = head
73+
while (current != null) {
74+
val next = current.next
75+
current.next = prev
76+
prev = current
77+
current = next
78+
}
79+
return prev
80+
}
81+
82+
@Test
83+
fun `정렬된 리스트 노드의 참조 체이닝을 특정 순서로 재정렬한다`() {
84+
val actual = ListNode.of(1,2,3,4,5).apply {
85+
reorderList(this)
86+
}
87+
actual.`val` shouldBe 1
88+
actual.next!!.`val` shouldBe 5
89+
actual.next!!.next!!.`val` shouldBe 2
90+
actual.next!!.next!!.next!!.`val` shouldBe 4
91+
actual.next!!.next!!.next!!.next!!.`val` shouldBe 3
92+
actual.next!!.next!!.next!!.next!!.next shouldBe null
93+
94+
ListNode.of(1,2,3,4,5,6).apply {
95+
reorderList(this)
96+
}
97+
}
98+
}

0 commit comments

Comments
 (0)