From 043df5a85feb8766154e55dbaaa8d27e7ea51b95 Mon Sep 17 00:00:00 2001 From: jeongdalma Date: Mon, 30 Sep 2024 13:42:45 +0900 Subject: [PATCH 1/4] =?UTF-8?q?8=EC=A3=BC=EC=B0=A8=20=EC=A0=9C=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- merge-two-sorted-lists/jdalma.kt | 45 ++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 merge-two-sorted-lists/jdalma.kt diff --git a/merge-two-sorted-lists/jdalma.kt b/merge-two-sorted-lists/jdalma.kt new file mode 100644 index 000000000..4102e794e --- /dev/null +++ b/merge-two-sorted-lists/jdalma.kt @@ -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)))))) + } +} From 5da9c09832fee55f98ead2a5a14cef501c94e13d Mon Sep 17 00:00:00 2001 From: jeongdalma Date: Tue, 1 Oct 2024 16:59:39 +0900 Subject: [PATCH 2/4] =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jdalma.kt | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 longest-repeating-character-replacement/jdalma.kt diff --git a/longest-repeating-character-replacement/jdalma.kt b/longest-repeating-character-replacement/jdalma.kt new file mode 100644 index 000000000..8eab9369a --- /dev/null +++ b/longest-repeating-character-replacement/jdalma.kt @@ -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() + 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 + } +} From 825e10fba38785e8d8c07895fc5e2e8a067cbbb7 Mon Sep 17 00:00:00 2001 From: jeongdalma Date: Wed, 2 Oct 2024 14:37:33 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- clone-graph/jdalma.kt | 94 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 clone-graph/jdalma.kt diff --git a/clone-graph/jdalma.kt b/clone-graph/jdalma.kt new file mode 100644 index 000000000..91da8cd59 --- /dev/null +++ b/clone-graph/jdalma.kt @@ -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 = 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): 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().apply { + this[node.`val`] = Node(node.`val`) + } + val queue: Queue = ArrayDeque().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 + } +} From eeafc3ff5fc9d2fde48de02f32711d234f4f8432 Mon Sep 17 00:00:00 2001 From: jeongdalma Date: Thu, 3 Oct 2024 14:24:05 +0900 Subject: [PATCH 4/4] =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- longest-common-subsequence/jdalma.kt | 65 ++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 longest-common-subsequence/jdalma.kt diff --git a/longest-common-subsequence/jdalma.kt b/longest-common-subsequence/jdalma.kt new file mode 100644 index 000000000..06ba1ad81 --- /dev/null +++ b/longest-common-subsequence/jdalma.kt @@ -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): 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 + } +}