Skip to content

Commit

Permalink
Merge pull request #504 from jdalma/main
Browse files Browse the repository at this point in the history
[์ •ํ˜„์ค€] 8์ฃผ์ฐจ ์ œ์ถœ
  • Loading branch information
jdalma authored Oct 5, 2024
2 parents e11c1b2 + eeafc3f commit 8fdb7bc
Show file tree
Hide file tree
Showing 4 changed files with 266 additions and 0 deletions.
94 changes: 94 additions & 0 deletions clone-graph/jdalma.kt
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
}
}
65 changes: 65 additions & 0 deletions longest-common-subsequence/jdalma.kt
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
}
}
62 changes: 62 additions & 0 deletions longest-repeating-character-replacement/jdalma.kt
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
}
}
45 changes: 45 additions & 0 deletions merge-two-sorted-lists/jdalma.kt
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))))))
}
}

0 comments on commit 8fdb7bc

Please sign in to comment.