From b8ab2d0ca3b185a0263556d26b731d83318d669a Mon Sep 17 00:00:00 2001 From: jeongdalma Date: Fri, 20 Sep 2024 16:54:25 +0900 Subject: [PATCH 1/3] =?UTF-8?q?6=EC=A3=BC=EC=B0=A8=20=EB=8B=B5=EC=95=88=20?= =?UTF-8?q?=EC=A0=9C=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- container-with-most-water/jdalma.kt | 40 ++++++++ .../jdalma.kt | 98 +++++++++++++++++++ valid-parentheses/jdalma.kt | 42 ++++++++ 3 files changed, 180 insertions(+) create mode 100644 container-with-most-water/jdalma.kt create mode 100644 design-add-and-search-words-data-structure/jdalma.kt create mode 100644 valid-parentheses/jdalma.kt diff --git a/container-with-most-water/jdalma.kt b/container-with-most-water/jdalma.kt new file mode 100644 index 000000000..12bf6e144 --- /dev/null +++ b/container-with-most-water/jdalma.kt @@ -0,0 +1,40 @@ +package leetcode_study + +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.Test +import kotlin.math.abs +import kotlin.math.max +import kotlin.math.min + +typealias Element = Pair + +class `container-with-most-wate` { + + /** + * 투 포인터를 활용하여 높이가 낮은 인덱스의 값을 한 칸씩 이동하며 최대 높이를 반환한다. + * TC: O(n), SC: O(1) + */ + fun maxArea(height: IntArray): Int { + var (left, right) = 0 to height.size - 1 + var result = 0 + + while (left < right) { + result = max(result, extent(Element(height[left], left), Element(height[right], right))) + if (height[left] < height[right]) { + left++ + } else { + right-- + } + } + return result + } + + private fun extent(e1: Element, e2: Element): Int { + return min(e1.first, e2.first) * abs(e1.second - e2.second) + } + + @Test + fun `입력받은 높이를 표현하는 정수 배열에서 받을 수 있는 최대의 물의 양을 반환한다`() { + maxArea(intArrayOf(1,8,6,2,5,4,8,3,7)) shouldBe 49 + } +} diff --git a/design-add-and-search-words-data-structure/jdalma.kt b/design-add-and-search-words-data-structure/jdalma.kt new file mode 100644 index 000000000..e0009ba0f --- /dev/null +++ b/design-add-and-search-words-data-structure/jdalma.kt @@ -0,0 +1,98 @@ +package leetcode_study + +import io.kotest.matchers.shouldBe +import leetcode_study.Type.* +import org.junit.jupiter.api.Test + +class `design-add-and-search-words-data-structure` { + + class Node { + var isEnd: Boolean = false + val next: MutableMap = mutableMapOf() + } + + class WordDictionary { + private val root = Node() + + /** + * TC: O(n), SC: O(n) + */ + fun addWord(word: String) { + var now = root + + for (index in word.indices) { + val node = + if (now.next.containsKey(word[index])) { now.next[word[index]] } + else Node().also { now.next[word[index]] = it } + node?.let { now = it } + } + now.isEnd = true + } + + /** + * TC: O(26^n), SC: O(n) + */ + fun search(word: String): Boolean { + + fun dfs(node: Node, word: String, index: Int): Boolean { + return if (index == word.length) node.isEnd + else if (word[index] == '.') { + node.next.values.any { dfs(it, word, index + 1) } + } + else { + node.next[word[index]]?.let { dfs(it, word, index + 1) } ?: false + } + } + + return dfs(this.root, word, 0) + } + } + + @Test + fun `문자열을 저장하고 검색하는 자료구조를 구현하라`() { + inputCommands( + Command(ADD, "bad"), + Command(ADD, "dad"), + Command(ADD, "mad"), + Command(SEARCH, "pad", false), + Command(SEARCH, "bad", true), + Command(SEARCH, ".ad", true), + Command(SEARCH, "b..", true), + ) + inputCommands( + Command(ADD, "at"), + Command(ADD, "and"), + Command(ADD, "an"), + Command(ADD, "add"), + Command(SEARCH, "a", false), + Command(SEARCH, ".at", false), + Command(ADD, "bat"), + Command(SEARCH,".at", true), + Command(SEARCH,"an.", true), + Command(SEARCH,"a.d.", false), + Command(SEARCH,"b.", false), + Command(SEARCH,"a.d", true), + Command(SEARCH,".", false) + ) + } + + private fun inputCommands(vararg commands: Command) { + val dictionary = WordDictionary() + for (command in commands) { + when(command.type) { + ADD -> dictionary.addWord(command.word) + SEARCH -> dictionary.search(command.word) shouldBe command.expect + } + } + } +} + +data class Command( + val type: Type, + val word: String, + val expect : Boolean? = null +) + +enum class Type { + ADD, SEARCH; +} diff --git a/valid-parentheses/jdalma.kt b/valid-parentheses/jdalma.kt new file mode 100644 index 000000000..2ef3143d8 --- /dev/null +++ b/valid-parentheses/jdalma.kt @@ -0,0 +1,42 @@ +package leetcode_study + +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.Test +import java.util.Deque +import java.util.ArrayDeque + +class `valid-parentheses` { + + /** + * 괄호의 쌍을 Stack을 활용하여 검증한다. + * TC: O(n), SC: O(n) + */ + fun isValid(s: String): Boolean { + if (s.length % 2 != 0) return false + val parentheses = mapOf( + '(' to ')', + '{' to '}', + '[' to ']' + ) + + val stack: Deque = ArrayDeque() + for (char in s) { + if (parentheses.containsKey(char)) { + stack.push(char) + } else if (stack.isEmpty() || parentheses[stack.pop()] != char){ + return false + } + } + return stack.isEmpty() + } + + @Test + fun `입력한 문자열의 괄호의 열림과 닫힘을 검증한다`() { + isValid("()") shouldBe true + isValid("{()}") shouldBe true + isValid("(){}[]") shouldBe true + + isValid("{(}") shouldBe false + isValid("){") shouldBe false + } +} From ff0b585fe8ae7d37a19d76eca13a19b32e0cc751 Mon Sep 17 00:00:00 2001 From: jeongdalma Date: Sat, 21 Sep 2024 13:23:37 +0900 Subject: [PATCH 2/3] =?UTF-8?q?LIS=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- longest-increasing-subsequence/jdalma.md | 72 ++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 longest-increasing-subsequence/jdalma.md diff --git a/longest-increasing-subsequence/jdalma.md b/longest-increasing-subsequence/jdalma.md new file mode 100644 index 000000000..26881bac3 --- /dev/null +++ b/longest-increasing-subsequence/jdalma.md @@ -0,0 +1,72 @@ +package leetcode_study + +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.Test + +class `longest-increasing-subsequence` { + + fun lengthOfLIS(nums: IntArray): Int { + return usingBinarySearch(nums) + } + + /** + * 이전 최장 수열 길이를 재사용한다. + * TC: O(n^2), SC: O(n) + */ + private fun usingDP(nums: IntArray): Int { + val dp = IntArray(nums.size) { 1 } + + for (i in 1 until nums.size) { + for (j in 0 until i) { + if (nums[i] > nums[j] && dp[i] < dp[j] + 1) { + dp[i] = dp[j] + 1 + } + } + } + + return dp.max() + } + + /** + * 최장 수열을 직접 갱신한다. + * TC: O(n * log n), SC: O(n) + */ + private fun usingBinarySearch(nums: IntArray): Int { + + fun binarySearch(list: List, number: Int): Int { + var (low, high) = 0 to list.size - 1 + + while (low <= high) { + val mid = (low + high) / 2 + if (list[mid] == number) { + return mid + } else if (list[mid] < number) { + low = mid + 1 + } else { + high = mid - 1 + } + } + return low + } + + val result = mutableListOf() + + for (num in nums) { + if (result.isEmpty() || result.last() < num) { + result.add(num) + } else { + result[binarySearch(result, num)] = num + } + } + + return result.size + } + + @Test + fun name() { + // lengthOfLIS(intArrayOf(10,9,2,5,3,7,101,18)) shouldBe 4 + // lengthOfLIS(intArrayOf(0,1,0,3,2,3)) shouldBe 4 + // lengthOfLIS(intArrayOf(0,1,2,3,4,5,6,7)) shouldBe 8 + lengthOfLIS(intArrayOf(4,10,4,3,8,9)) shouldBe 3 + } +} From 8e4a8b12d96eadb0a9f14881adece01d715e6731 Mon Sep 17 00:00:00 2001 From: jeongdalma Date: Sat, 21 Sep 2024 13:24:29 +0900 Subject: [PATCH 3/3] =?UTF-8?q?LIS=20=EB=AC=B8=EC=A0=9C=20=ED=99=95?= =?UTF-8?q?=EC=9E=A5=EC=9E=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- longest-increasing-subsequence/{jdalma.md => jdalma.kt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename longest-increasing-subsequence/{jdalma.md => jdalma.kt} (100%) diff --git a/longest-increasing-subsequence/jdalma.md b/longest-increasing-subsequence/jdalma.kt similarity index 100% rename from longest-increasing-subsequence/jdalma.md rename to longest-increasing-subsequence/jdalma.kt