Skip to content

Commit 8fdb7bc

Browse files
authored
Merge pull request #504 from jdalma/main
[정현준] 8주차 제출
2 parents e11c1b2 + eeafc3f commit 8fdb7bc

File tree

4 files changed

+266
-0
lines changed

4 files changed

+266
-0
lines changed

clone-graph/jdalma.kt

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.shouldBe
4+
import org.junit.jupiter.api.Test
5+
import java.lang.RuntimeException
6+
import java.util.ArrayDeque
7+
import java.util.Queue
8+
9+
class `clone-graph` {
10+
11+
data class Node(var `val`: Int) {
12+
var neighbors: ArrayList<Node?> = ArrayList()
13+
}
14+
15+
fun cloneGraph(node: Node?): Node? {
16+
if (node == null) return null
17+
18+
return usingBFS(node)
19+
}
20+
21+
/**
22+
* TC: O(n), SC: O(n)
23+
*/
24+
private fun usingDFS(node: Node): Node {
25+
26+
fun dfs(node: Node, nodes: MutableMap<Int, Node>): Node {
27+
nodes[node.`val`]?.let {
28+
return it
29+
}
30+
val copy = Node(node.`val`)
31+
nodes[node.`val`] = copy
32+
33+
for (near in node.neighbors.filterNotNull()) {
34+
copy.neighbors.add(dfs(near, nodes))
35+
}
36+
37+
return copy
38+
}
39+
return dfs(node, mutableMapOf())
40+
}
41+
42+
/**
43+
* TC: O(n), SC: O(n)
44+
*/
45+
private fun usingBFS(node: Node): Node {
46+
val nodes = mutableMapOf<Int, Node>().apply {
47+
this[node.`val`] = Node(node.`val`)
48+
}
49+
val queue: Queue<Node> = ArrayDeque<Node>().apply {
50+
this.offer(node)
51+
}
52+
53+
while (queue.isNotEmpty()) {
54+
val now = queue.poll()
55+
val copy = nodes[now.`val`] ?: throw RuntimeException()
56+
for (near in now.neighbors.filterNotNull()) {
57+
if (!nodes.containsKey(near.`val`)) {
58+
nodes[near.`val`] = Node(near.`val`)
59+
queue.add(near)
60+
}
61+
copy.neighbors.add(nodes[near.`val`])
62+
}
63+
}
64+
return nodes[node.`val`] ?: Node(node.`val`)
65+
}
66+
67+
private fun fixture(): Node {
68+
val one = Node(1)
69+
val two = Node(2)
70+
val three = Node(3)
71+
val four = Node(4)
72+
73+
one.neighbors.add(two)
74+
one.neighbors.add(four)
75+
two.neighbors.add(one)
76+
two.neighbors.add(three)
77+
three.neighbors.add(two)
78+
three.neighbors.add(four)
79+
four.neighbors.add(one)
80+
four.neighbors.add(three)
81+
82+
return one
83+
}
84+
85+
@Test
86+
fun `입력받은 노드의 깊은 복사본을 반환한다`() {
87+
val actualNode = fixture()
88+
val expectNode = cloneGraph(actualNode)
89+
actualNode shouldBe expectNode
90+
91+
actualNode.`val` = 9999
92+
expectNode!!.`val` shouldBe 1
93+
}
94+
}

longest-common-subsequence/jdalma.kt

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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 `longest-common-subsequence` {
8+
9+
fun longestCommonSubsequence(text1: String, text2: String): Int {
10+
return usingDP(text1, text2)
11+
}
12+
13+
/**
14+
* TC: O(2^(n + m)), SC: O(n + m) 시간초과!!!
15+
*/
16+
private fun usingBruteForce(text1: String, text2: String): Int {
17+
18+
fun dfs(i: Int, j: Int): Int =
19+
if (i == text1.length || j == text2.length) 0
20+
else if(text1[i] == text2[j]) 1 + dfs(i + 1, j + 1)
21+
else max(dfs(i + 1, j), dfs(i, j + 1))
22+
23+
return dfs(0, 0)
24+
}
25+
26+
/**
27+
* TC: O(n * m), SC: O(n * m)
28+
*/
29+
private fun usingMemoization(text1: String, text2: String): Int {
30+
31+
fun dfs(i: Int, j: Int, memo: Array<IntArray>): Int {
32+
if (i == text1.length || j == text2.length) return 0
33+
else if (memo[i][j] != -1) return memo[i][j]
34+
35+
memo[i][j] = if(text1[i] == text2[j]) 1 + dfs(i + 1, j + 1, memo)
36+
else max(dfs(i + 1, j, memo), dfs(i, j + 1, memo))
37+
38+
return memo[i][j]
39+
}
40+
val memo = Array(text1.length) { IntArray(text2.length) { -1 } }
41+
return dfs(0, 0, memo)
42+
}
43+
44+
/**
45+
* TC: O(n * m), SC: O(n * m)
46+
*/
47+
private fun usingDP(text1: String, text2: String): Int {
48+
val dp = Array(text1.length + 1) { IntArray(text2.length + 1) }
49+
for (i in text1.indices) {
50+
for (j in text2.indices) {
51+
dp[i + 1][j + 1] = if (text1[i] == text2[j]) dp[i][j] + 1
52+
else max(dp[i + 1][j], dp[i][j + 1])
53+
}
54+
}
55+
return dp[text1.length][text2.length]
56+
}
57+
58+
@Test
59+
fun `입력받은 두 문자열의 가장 긴 공통 부분 수열의 길이를 반환하라`() {
60+
longestCommonSubsequence("abcde", "ace") shouldBe 3
61+
longestCommonSubsequence("abc", "abc") shouldBe 3
62+
longestCommonSubsequence("abcdefghi", "defi") shouldBe 4
63+
longestCommonSubsequence("abc", "def") shouldBe 0
64+
}
65+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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 `longest-repeating-character-replacement` {
8+
9+
fun characterReplacement(s: String, k: Int): Int {
10+
return usingSlidingWindow(s, k)
11+
}
12+
13+
/**
14+
* TC: O(n^3), SC: O(1) 시간초과 !!!
15+
*/
16+
private fun usingBruteForce(s: String, k: Int): Int {
17+
var result = 0
18+
19+
for (start in s.indices) {
20+
for (end in start until s.length) {
21+
val counter = mutableMapOf<Char, Int>()
22+
for (i in start .. end) {
23+
counter[s[i]] = counter.getOrDefault(s[i], 0) + 1
24+
}
25+
26+
val maxCount = counter.values.maxOrNull() ?: 0
27+
if ((end - start + 1) - maxCount <= k) {
28+
result = max(result, end - start + 1)
29+
}
30+
}
31+
}
32+
33+
return result
34+
}
35+
36+
/**
37+
* TC: O(n), SC: O(1)
38+
*/
39+
private fun usingSlidingWindow(s: String, k: Int): Int {
40+
var (maxLength, start) = 0 to 0
41+
val count = IntArray(26)
42+
43+
for (end in s.indices) {
44+
count[s[end] - 'A']++
45+
while (end - start + 1 - count.max() > k) {
46+
count[s[start] - 'A']--
47+
start++
48+
}
49+
maxLength = max(end - start + 1, maxLength)
50+
}
51+
52+
return maxLength
53+
}
54+
55+
@Test
56+
fun `문자열이 주어졌을 때 동일한 문자를 포함하는 가장 긴 부분 문자열의 길이를 반환한다 문자는 최대 k번 변경할 수 있다`() {
57+
characterReplacement("ABAB", 2) shouldBe 4
58+
characterReplacement("AABAB", 2) shouldBe 5
59+
characterReplacement("AABAB", 1) shouldBe 4
60+
characterReplacement("AABBAB", 1) shouldBe 4
61+
}
62+
}

merge-two-sorted-lists/jdalma.kt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.shouldBe
4+
import org.junit.jupiter.api.Test
5+
6+
class `merge-two-sorted-lists` {
7+
8+
data class ListNode(
9+
var `val`: Int,
10+
var next: ListNode? = null
11+
)
12+
13+
/**
14+
* TC: O(n + m), SC: O(1)
15+
*/
16+
fun mergeTwoLists(list1: ListNode?, list2: ListNode?): ListNode? {
17+
var (l1, l2) = list1 to list2
18+
var current = ListNode(-1)
19+
val result: ListNode = current
20+
21+
while (l1 != null && l2 != null) {
22+
if (l1.`val` < l2.`val`) {
23+
current.next = l1
24+
l1 = l1.next
25+
} else {
26+
current.next = l2
27+
l2 = l2.next
28+
}
29+
current.next?.let { current = it }
30+
}
31+
32+
if (l1 != null) current.next = l1
33+
if (l2 != null) current.next = l2
34+
35+
return result.next
36+
}
37+
38+
@Test
39+
fun `두 개의 리스트 노드를 정렬하여 병합한다`() {
40+
mergeTwoLists(
41+
ListNode(1,ListNode(2,ListNode(4))),
42+
ListNode(1,ListNode(3,ListNode(4)))
43+
) shouldBe ListNode(1,ListNode(1,ListNode(2, ListNode(3, ListNode(4, ListNode(4))))))
44+
}
45+
}

0 commit comments

Comments
 (0)