Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[정현준] 6주차 답안 제출 #475

Merged
merged 3 commits into from
Sep 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions container-with-most-water/jdalma.kt
Original file line number Diff line number Diff line change
@@ -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<Int,Int>

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
}
}
98 changes: 98 additions & 0 deletions design-add-and-search-words-data-structure/jdalma.kt
Original file line number Diff line number Diff line change
@@ -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<Char, Node> = 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;
}
72 changes: 72 additions & 0 deletions longest-increasing-subsequence/jdalma.kt
Original file line number Diff line number Diff line change
@@ -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<Int>, 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<Int>()

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
}
}
42 changes: 42 additions & 0 deletions valid-parentheses/jdalma.kt
Original file line number Diff line number Diff line change
@@ -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<Char> = 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
}
}