-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #504 from jdalma/main
[์ ํ์ค] 8์ฃผ์ฐจ ์ ์ถ
- Loading branch information
Showing
4 changed files
with
266 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package leetcode_study | ||
|
||
import io.kotest.matchers.shouldBe | ||
import org.junit.jupiter.api.Test | ||
import java.lang.RuntimeException | ||
import java.util.ArrayDeque | ||
import java.util.Queue | ||
|
||
class `clone-graph` { | ||
|
||
data class Node(var `val`: Int) { | ||
var neighbors: ArrayList<Node?> = ArrayList() | ||
} | ||
|
||
fun cloneGraph(node: Node?): Node? { | ||
if (node == null) return null | ||
|
||
return usingBFS(node) | ||
} | ||
|
||
/** | ||
* TC: O(n), SC: O(n) | ||
*/ | ||
private fun usingDFS(node: Node): Node { | ||
|
||
fun dfs(node: Node, nodes: MutableMap<Int, Node>): Node { | ||
nodes[node.`val`]?.let { | ||
return it | ||
} | ||
val copy = Node(node.`val`) | ||
nodes[node.`val`] = copy | ||
|
||
for (near in node.neighbors.filterNotNull()) { | ||
copy.neighbors.add(dfs(near, nodes)) | ||
} | ||
|
||
return copy | ||
} | ||
return dfs(node, mutableMapOf()) | ||
} | ||
|
||
/** | ||
* TC: O(n), SC: O(n) | ||
*/ | ||
private fun usingBFS(node: Node): Node { | ||
val nodes = mutableMapOf<Int, Node>().apply { | ||
this[node.`val`] = Node(node.`val`) | ||
} | ||
val queue: Queue<Node> = ArrayDeque<Node>().apply { | ||
this.offer(node) | ||
} | ||
|
||
while (queue.isNotEmpty()) { | ||
val now = queue.poll() | ||
val copy = nodes[now.`val`] ?: throw RuntimeException() | ||
for (near in now.neighbors.filterNotNull()) { | ||
if (!nodes.containsKey(near.`val`)) { | ||
nodes[near.`val`] = Node(near.`val`) | ||
queue.add(near) | ||
} | ||
copy.neighbors.add(nodes[near.`val`]) | ||
} | ||
} | ||
return nodes[node.`val`] ?: Node(node.`val`) | ||
} | ||
|
||
private fun fixture(): Node { | ||
val one = Node(1) | ||
val two = Node(2) | ||
val three = Node(3) | ||
val four = Node(4) | ||
|
||
one.neighbors.add(two) | ||
one.neighbors.add(four) | ||
two.neighbors.add(one) | ||
two.neighbors.add(three) | ||
three.neighbors.add(two) | ||
three.neighbors.add(four) | ||
four.neighbors.add(one) | ||
four.neighbors.add(three) | ||
|
||
return one | ||
} | ||
|
||
@Test | ||
fun `์ ๋ ฅ๋ฐ์ ๋ ธ๋์ ๊น์ ๋ณต์ฌ๋ณธ์ ๋ฐํํ๋ค`() { | ||
val actualNode = fixture() | ||
val expectNode = cloneGraph(actualNode) | ||
actualNode shouldBe expectNode | ||
|
||
actualNode.`val` = 9999 | ||
expectNode!!.`val` shouldBe 1 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package leetcode_study | ||
|
||
import io.kotest.matchers.shouldBe | ||
import org.junit.jupiter.api.Test | ||
import kotlin.math.max | ||
|
||
class `longest-common-subsequence` { | ||
|
||
fun longestCommonSubsequence(text1: String, text2: String): Int { | ||
return usingDP(text1, text2) | ||
} | ||
|
||
/** | ||
* TC: O(2^(n + m)), SC: O(n + m) ์๊ฐ์ด๊ณผ!!! | ||
*/ | ||
private fun usingBruteForce(text1: String, text2: String): Int { | ||
|
||
fun dfs(i: Int, j: Int): Int = | ||
if (i == text1.length || j == text2.length) 0 | ||
else if(text1[i] == text2[j]) 1 + dfs(i + 1, j + 1) | ||
else max(dfs(i + 1, j), dfs(i, j + 1)) | ||
|
||
return dfs(0, 0) | ||
} | ||
|
||
/** | ||
* TC: O(n * m), SC: O(n * m) | ||
*/ | ||
private fun usingMemoization(text1: String, text2: String): Int { | ||
|
||
fun dfs(i: Int, j: Int, memo: Array<IntArray>): Int { | ||
if (i == text1.length || j == text2.length) return 0 | ||
else if (memo[i][j] != -1) return memo[i][j] | ||
|
||
memo[i][j] = if(text1[i] == text2[j]) 1 + dfs(i + 1, j + 1, memo) | ||
else max(dfs(i + 1, j, memo), dfs(i, j + 1, memo)) | ||
|
||
return memo[i][j] | ||
} | ||
val memo = Array(text1.length) { IntArray(text2.length) { -1 } } | ||
return dfs(0, 0, memo) | ||
} | ||
|
||
/** | ||
* TC: O(n * m), SC: O(n * m) | ||
*/ | ||
private fun usingDP(text1: String, text2: String): Int { | ||
val dp = Array(text1.length + 1) { IntArray(text2.length + 1) } | ||
for (i in text1.indices) { | ||
for (j in text2.indices) { | ||
dp[i + 1][j + 1] = if (text1[i] == text2[j]) dp[i][j] + 1 | ||
else max(dp[i + 1][j], dp[i][j + 1]) | ||
} | ||
} | ||
return dp[text1.length][text2.length] | ||
} | ||
|
||
@Test | ||
fun `์ ๋ ฅ๋ฐ์ ๋ ๋ฌธ์์ด์ ๊ฐ์ฅ ๊ธด ๊ณตํต ๋ถ๋ถ ์์ด์ ๊ธธ์ด๋ฅผ ๋ฐํํ๋ผ`() { | ||
longestCommonSubsequence("abcde", "ace") shouldBe 3 | ||
longestCommonSubsequence("abc", "abc") shouldBe 3 | ||
longestCommonSubsequence("abcdefghi", "defi") shouldBe 4 | ||
longestCommonSubsequence("abc", "def") shouldBe 0 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package leetcode_study | ||
|
||
import io.kotest.matchers.shouldBe | ||
import org.junit.jupiter.api.Test | ||
import kotlin.math.max | ||
|
||
class `longest-repeating-character-replacement` { | ||
|
||
fun characterReplacement(s: String, k: Int): Int { | ||
return usingSlidingWindow(s, k) | ||
} | ||
|
||
/** | ||
* TC: O(n^3), SC: O(1) ์๊ฐ์ด๊ณผ !!! | ||
*/ | ||
private fun usingBruteForce(s: String, k: Int): Int { | ||
var result = 0 | ||
|
||
for (start in s.indices) { | ||
for (end in start until s.length) { | ||
val counter = mutableMapOf<Char, Int>() | ||
for (i in start .. end) { | ||
counter[s[i]] = counter.getOrDefault(s[i], 0) + 1 | ||
} | ||
|
||
val maxCount = counter.values.maxOrNull() ?: 0 | ||
if ((end - start + 1) - maxCount <= k) { | ||
result = max(result, end - start + 1) | ||
} | ||
} | ||
} | ||
|
||
return result | ||
} | ||
|
||
/** | ||
* TC: O(n), SC: O(1) | ||
*/ | ||
private fun usingSlidingWindow(s: String, k: Int): Int { | ||
var (maxLength, start) = 0 to 0 | ||
val count = IntArray(26) | ||
|
||
for (end in s.indices) { | ||
count[s[end] - 'A']++ | ||
while (end - start + 1 - count.max() > k) { | ||
count[s[start] - 'A']-- | ||
start++ | ||
} | ||
maxLength = max(end - start + 1, maxLength) | ||
} | ||
|
||
return maxLength | ||
} | ||
|
||
@Test | ||
fun `๋ฌธ์์ด์ด ์ฃผ์ด์ก์ ๋ ๋์ผํ ๋ฌธ์๋ฅผ ํฌํจํ๋ ๊ฐ์ฅ ๊ธด ๋ถ๋ถ ๋ฌธ์์ด์ ๊ธธ์ด๋ฅผ ๋ฐํํ๋ค ๋ฌธ์๋ ์ต๋ k๋ฒ ๋ณ๊ฒฝํ ์ ์๋ค`() { | ||
characterReplacement("ABAB", 2) shouldBe 4 | ||
characterReplacement("AABAB", 2) shouldBe 5 | ||
characterReplacement("AABAB", 1) shouldBe 4 | ||
characterReplacement("AABBAB", 1) shouldBe 4 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package leetcode_study | ||
|
||
import io.kotest.matchers.shouldBe | ||
import org.junit.jupiter.api.Test | ||
|
||
class `merge-two-sorted-lists` { | ||
|
||
data class ListNode( | ||
var `val`: Int, | ||
var next: ListNode? = null | ||
) | ||
|
||
/** | ||
* TC: O(n + m), SC: O(1) | ||
*/ | ||
fun mergeTwoLists(list1: ListNode?, list2: ListNode?): ListNode? { | ||
var (l1, l2) = list1 to list2 | ||
var current = ListNode(-1) | ||
val result: ListNode = current | ||
|
||
while (l1 != null && l2 != null) { | ||
if (l1.`val` < l2.`val`) { | ||
current.next = l1 | ||
l1 = l1.next | ||
} else { | ||
current.next = l2 | ||
l2 = l2.next | ||
} | ||
current.next?.let { current = it } | ||
} | ||
|
||
if (l1 != null) current.next = l1 | ||
if (l2 != null) current.next = l2 | ||
|
||
return result.next | ||
} | ||
|
||
@Test | ||
fun `๋ ๊ฐ์ ๋ฆฌ์คํธ ๋ ธ๋๋ฅผ ์ ๋ ฌํ์ฌ ๋ณํฉํ๋ค`() { | ||
mergeTwoLists( | ||
ListNode(1,ListNode(2,ListNode(4))), | ||
ListNode(1,ListNode(3,ListNode(4))) | ||
) shouldBe ListNode(1,ListNode(1,ListNode(2, ListNode(3, ListNode(4, ListNode(4)))))) | ||
} | ||
} |