Skip to content

Commit ac59579

Browse files
authored
Merge pull request #347 from jdalma/main
[์ •ํ˜„์ค€] 2์ฃผ์ฐจ ๋‹ต์•ˆ ์ œ์ถœ
2 parents 8f47a65 + b02d06f commit ac59579

File tree

5 files changed

+307
-0
lines changed

5 files changed

+307
-0
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.equals.shouldBeEqual
4+
import org.junit.jupiter.api.Test
5+
6+
class `construct-binary-tree-from-preorder-and-inorder-traversal` {
7+
8+
/**
9+
* preorder : ํ˜„์žฌ(๋ถ€๋ชจ) ๋…ธ๋“œ๋ถ€ํ„ฐ ์™ผ์ชฝ ์ž์‹ ๋…ธ๋“œ, ์˜ค๋ฅธ์ชฝ ์ž์‹ ๋…ธ๋“œ
10+
* inorder : ์™ผ์ชฝ ์ž์‹ ๋…ธ๋“œ ๋ถ€ํ„ฐ ๋ถ€๋ชจ ๋…ธ๋“œ, ์˜ค๋ฅธ์ชฝ ์ž์‹ ๋…ธ๋“œ
11+
*/
12+
fun buildTree(preorder: IntArray, inorder: IntArray): TreeNode? {
13+
val inorderIndices = inorder.withIndex().associate { it.value to it.index }
14+
return traversal(preorder, inorder, inorderIndices)
15+
}
16+
17+
/**
18+
* preorder์—์„œ ์กฐํšŒํ•œ ๋ถ€๋ชจ ๋…ธ๋“œ์˜ ๊ฐ’์€ inorder์˜ ์ค‘๊ฐ„์— ์œ„์น˜ํ•œ๋‹ค.
19+
* ๊ทธ ์ค‘๊ฐ„ ์œ„์น˜ ๊ธฐ์ค€์œผ๋กœ ์™ผ์ชฝ ๋…ธ๋“œ, ์˜ค๋ฅธ์ชฝ ๋…ธ๋“œ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ ์žฌ๊ท€์ ์œผ๋กœ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค.
20+
* ์‹œ๊ฐ„๋ณต์žก๋„: O(n), ๊ณต๊ฐ„๋ณต์žก๋„: O(n)
21+
*/
22+
private fun traversal(
23+
preorder: IntArray, inorder: IntArray, inorderIndices: Map<Int, Int>,
24+
preStart: Int = 0, inStart: Int = 0, inEnd: Int = inorder.size - 1
25+
): TreeNode? {
26+
if (preStart > preorder.size - 1 || inStart > inEnd) {
27+
return null
28+
}
29+
val value = preorder[preStart]
30+
val rootIndexInInorder = inorderIndices[value]!!
31+
32+
return TreeNode(value).apply {
33+
this.left = traversal(
34+
preorder, inorder, inorderIndices,
35+
preStart + 1, inStart, rootIndexInInorder - 1
36+
)
37+
this.right = traversal(
38+
preorder, inorder, inorderIndices,
39+
preStart + rootIndexInInorder - inStart + 1, rootIndexInInorder + 1, inEnd
40+
)
41+
}
42+
}
43+
44+
@Test
45+
fun `์ „์œ„ ์ˆœํšŒ, ์ค‘์œ„ ์ˆœํšŒ ์ˆœ์„œ์˜ ์ •์ˆ˜ ๋ฐฐ์—ด์„ ๊ธฐ์ค€์œผ๋กœ ์ด์ง„ํŠธ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•œ๋‹ค`() {
46+
val actual = buildTree(intArrayOf(3,9,20,15,7), intArrayOf(9,3,15,20,7))!!
47+
val expect = TreeNode.of(3,9,20,null,null,15,7)!!
48+
49+
actual shouldBeEqual expect
50+
51+
val actual1 = buildTree(intArrayOf(3,9,8,10,20,15,7), intArrayOf(8,9,10,3,15,20,7))!!
52+
val expect1 = TreeNode.of(3,9,20,8,10,15,7)!!
53+
54+
actual1 shouldBeEqual expect1
55+
}
56+
}

โ€Žcounting-bits/jdalma.kt

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.shouldBe
4+
import org.junit.jupiter.api.Test
5+
6+
class `counting-bits` {
7+
8+
fun countBits(n: Int): IntArray {
9+
return usingDPAndLeastSignificantBit(n)
10+
}
11+
12+
// 1. ์ž…๋ ฅ๋ฐ›์€ ์ •์ˆ˜๋งŒํผ ์ˆœํšŒํ•˜๋ฉฐ bit ์นด์šดํŠธ
13+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(n * log(n)), ๊ณต๊ฐ„๋ณต์žก๋„: O(1)
14+
private fun usingBinary(n: Int): IntArray {
15+
fun binary(n: Int): Int {
16+
var calc = n
17+
var count = 0
18+
while(calc > 0) {
19+
if (calc % 2 != 0) {
20+
count++
21+
}
22+
calc /= 2
23+
}
24+
return count
25+
}
26+
27+
return (0 .. n).map { binary(it) }.toIntArray()
28+
}
29+
30+
// 2. MSB, ์ฆ‰ ์ตœ์ƒ์œ„ ๋น„ํŠธ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์‹ญ์ง„์ˆ˜๊ฐ€ ๋‘ ๋ฐฐ๊ฐ€ ๋ ๋•Œ๋งˆ๋‹ค MSB๋ฅผ ๊ฐฑ์‹ ํ•˜์—ฌ ์ด์ „์˜ ๊ฒฐ๊ณผ๋ฅผ ํ™œ์šฉ
31+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(n), ๊ณต๊ฐ„๋ณต์žก๋„: O(n)
32+
private fun usingDPAndMostSignificantBit(n: Int): IntArray {
33+
val dp = IntArray(n + 1)
34+
var msb = 1
35+
36+
for (index in 1 .. n) {
37+
if (index == msb shl 1) {
38+
msb = index
39+
}
40+
dp[index] = 1 + dp[index - msb]
41+
}
42+
43+
return dp
44+
}
45+
46+
// 3. ์ตœํ•˜์œ„ ๋น„ํŠธ๋ฅผ ์ œ๊ฑฐํ•œ ๊ฒฐ๊ณผ๋ฅผ ์žฌํ™œ์šฉํ•œ๋‹ค. (์ตœํ•˜์œ„ ๋น„ํŠธ๋ฅผ ์ œ๊ฑฐํ•œ ๊ฒฐ๊ณผ) + (ํ˜„์žฌ ์‹ญ์ง„์ˆ˜์˜ ์ตœํ•˜์œ„๋น„ํŠธ)
47+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(n), ๊ณต๊ฐ„๋ณต์žก๋„: O(n)
48+
private fun usingDPAndLeastSignificantBit(n: Int): IntArray {
49+
val dp = IntArray(n + 1)
50+
for (index in 1 .. n) {
51+
dp[index] = dp[index shr 1] + (index and 1)
52+
}
53+
54+
return dp
55+
}
56+
57+
@Test
58+
fun `์ •์ˆ˜๊ฐ€ ์ฃผ์–ด์ง€๋ฉด ๊ฐ i(0 ~ i)์— ๋Œ€ํ•ด ์ด์ง„ ํ‘œํ˜„์—์„œ 1์˜ ๊ฐœ์ˆ˜๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค`() {
59+
countBits(2) shouldBe intArrayOf(0,1,1)
60+
countBits(5) shouldBe intArrayOf(0,1,1,2,1,2)
61+
}
62+
}

โ€Ždecode-ways/jdalma.kt

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.shouldBe
4+
import org.junit.jupiter.api.Test
5+
6+
class `decode-ways` {
7+
8+
fun numDecodings(s: String): Int {
9+
return usingOptimizedDP(s)
10+
}
11+
12+
/**
13+
* 1. ๋ฌธ์ž์—ด์˜ ์ฒซ ์ธ๋ฑ์Šค๋ถ€ํ„ฐ DFS๋กœ ํ™•์ธํ•˜๋ฉด์„œ ๊ฒฐ๊ณผ๋ฅผ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค. โ†’ ์‹œ๊ฐ„์ดˆ๊ณผ
14+
* 0๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋Š” ๋ฌธ์ž์—ด์€ ์กด์žฌํ•˜์ง€ ์•Š๊ธฐ์— ๋ฐ”๋กœ 0์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๊ณ  ๊ทธ ๋’ค ์ˆซ์ž๋ถ€ํ„ฐ DFS๋ฅผ ์—ฐ์ด์–ด ์‹คํ–‰ํ•œ๋‹ค.
15+
* ์‹œ๊ฐ„๋ณต์žก๋„: O(2^n), ๊ณต๊ฐ„๋ณต์žก๋„: O(n)
16+
*/
17+
private fun usingDfs(s: String): Int {
18+
fun dfs(index: Int): Int =
19+
if (index == s.length) 1
20+
else if (s[index] == '0') 0
21+
else if (index + 1 < s.length && (s[index] == '1' || (s[index] == '2' && s[index + 1] < '7')) )
22+
dfs(index + 1) + dfs(index + 2)
23+
else dfs(index + 1)
24+
25+
return dfs(0)
26+
}
27+
28+
/**
29+
* 2. 1๋ฒˆ ํ’€์ด์—์„œ ์ค‘๋ณต๋˜๋Š” ์—ฐ์‚ฐ์— top-down ๋ฐฉํ–ฅ์œผ๋กœ ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ์ ์šฉ
30+
* ์‹œ๊ฐ„๋ณต์žก๋„: O(n), ๊ณต๊ฐ„๋ณต์žก๋„: O(n)
31+
*/
32+
private fun usingMemoization(s: String): Int {
33+
fun dfs(index: Int, mem: IntArray): Int {
34+
println(index)
35+
mem[index] = if (index == s.length) 1
36+
else if (s[index] == '0') 0
37+
else if (mem[index] != 0) mem[index]
38+
else if (index + 1 < s.length && (s[index] == '1' || (s[index] == '2' && s[index + 1] < '7')) )
39+
dfs(index + 1, mem) + dfs(index + 2, mem)
40+
else dfs(index + 1, mem)
41+
42+
return mem[index]
43+
}
44+
return dfs(0, IntArray(s.length + 1) { 0 })
45+
}
46+
47+
/**
48+
* 3. ๋งˆ์ง€๋ง‰ ์ˆซ์ž๋ถ€ํ„ฐ bottom-up ๋ฐฉํ–ฅ DP
49+
* ์‹œ๊ฐ„๋ณต์žก๋„: O(n), ๊ณต๊ฐ„๋ณต์žก๋„: O(n)
50+
*/
51+
private fun usingDP(s: String): Int {
52+
val dp = IntArray(s.length + 1).apply {
53+
this[s.length] = 1
54+
}
55+
56+
(s.length - 1 downTo 0).forEach { index ->
57+
if (s[index] == '0') dp[index] = 0
58+
else if(index + 1 < s.length && (s[index] == '1' || (s[index] == '2' && s[index + 1] < '7')))
59+
dp[index] = dp[index + 1] + dp[index + 2]
60+
else dp[index] = dp[index + 1]
61+
}
62+
63+
return dp[0]
64+
}
65+
66+
/**
67+
* 4. ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  DP ์ ์šฉ
68+
* ์‹œ๊ฐ„๋ณต์žก๋„: O(n), ๊ณต๊ฐ„๋ณต์žก๋„: O(1)
69+
*/
70+
private fun usingOptimizedDP(s: String): Int {
71+
var (memo, result) = 0 to 1
72+
73+
(s.length - 1 downTo 0).forEach { index ->
74+
var tmp = if (s[index] == '0') 0 else result
75+
76+
if (index + 1 < s.length && (s[index] == '1' || (s[index] == '2' && s[index + 1] < '7'))) {
77+
tmp += memo
78+
}
79+
memo = result
80+
result = tmp
81+
}
82+
83+
return result
84+
}
85+
86+
@Test
87+
fun `์ž…๋ ฅ๋ฐ›์€ ๋ฌธ์ž์—ด์˜ ๋””์ฝ”๋”ฉ ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ์˜ ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค`() {
88+
numDecodings("12") shouldBe 2
89+
numDecodings("226") shouldBe 3
90+
numDecodings("06") shouldBe 0
91+
numDecodings("1011") shouldBe 2
92+
numDecodings("10112266") shouldBe 8
93+
numDecodings("1025") shouldBe 2
94+
}
95+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.equals.shouldBeEqual
4+
import org.junit.jupiter.api.Test
5+
6+
/**
7+
* ์ธ์ฝ”๋”ฉ๊ณผ ๋””์ฝ”๋”ฉ์„ ํ•ด๊ฒฐํ•  ๋•Œ ๊ตฌ๋ถ„์ž๋ฅผ 256๊ฐœ์˜ ASCII ๋ฌธ์ž ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
8+
* ์‹œ๊ฐ„๋ณต์žก๋„: O(n), ๊ณต๊ฐ„๋ณต์žก๋„: O(1)
9+
*/
10+
class `encode-and-decode-strings` {
11+
12+
private val DELIMITER = ":"
13+
14+
fun encode(strings: List<String>): String {
15+
return strings.joinToString(separator = "") { e -> "${e.length}$DELIMITER$e" }
16+
}
17+
18+
fun decode(string: String): List<String> {
19+
var index = 0
20+
val result = mutableListOf<String>()
21+
while (index < string.length) {
22+
val delimiterIndex = string.indexOf(DELIMITER, startIndex = index)
23+
val size = string.substring(index, delimiterIndex).toInt()
24+
result.add(string.substring(delimiterIndex + 1, delimiterIndex + size + 1))
25+
index = delimiterIndex + size + 1
26+
}
27+
return result
28+
}
29+
30+
@Test
31+
fun `๋ฌธ์ž์—ด ๋ชฉ๋ก์„ ํ•˜๋‚˜์˜ ๋ฌธ์ž์—ด๋กœ ์ธ์ฝ”๋”ฉํ•œ๋‹ค`() {
32+
encode(listOf("leet","co:de","l:o:v:e","you")) shouldBeEqual "4:leet5:co:de7:l:o:v:e3:you"
33+
}
34+
35+
@Test
36+
fun `๋ฌธ์ž์—ด์„ ๋ฌธ์ž์—ด ๋ชฉ๋ก์œผ๋กœ ๋””์ฝ”๋”ฉํ•œ๋‹ค`() {
37+
decode("4:leet5:co:de7:l:o:v:e3:you") shouldBeEqual listOf("leet","co:de","l:o:v:e","you")
38+
}
39+
}

โ€Žvalid-anagram/jdalma.kt

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package leetcode_study
2+
3+
import org.junit.jupiter.api.Test
4+
5+
class `valid-anagram` {
6+
7+
fun isAnagram(s: String, t: String): Boolean {
8+
return usingArray(s, t)
9+
}
10+
11+
// 1. ๋‘ ๋ฌธ์ž์—ด์„ ์ •๋ ฌํ•˜์—ฌ ๋น„๊ตํ•œ๋‹ค.
12+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(n * log(n)), ๊ณต๊ฐ„๋ณต์žก๋„: O(n)
13+
private fun usingSort(s: String, t: String): Boolean {
14+
val sorted1 = s.toCharArray().apply { this.sort() }
15+
val sorted2 = t.toCharArray().apply { this.sort() }
16+
17+
return sorted1.contentEquals(sorted2)
18+
}
19+
20+
// 2. ๋ฐฐ์—ด์— ๋ฌธ์ž ์ˆ˜ ๊ฐ€๊ฐ
21+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(n), ๊ณต๊ฐ„๋ณต์žก๋„: O(n)
22+
private fun usingArray(s: String, t: String): Boolean {
23+
if (s.length != t.length) {
24+
return false
25+
}
26+
27+
/* ํ•ด์‹œ๋งต ์‚ฌ์šฉ
28+
val map: Map<Char, Int> = mutableMapOf<Char, Int>().apply {
29+
(s.indices).forEach { index ->
30+
this[s[index]] = this.getOrDefault(s[index], 0) + 1
31+
this[t[index]] = this.getOrDefault(t[index], 0) - 1
32+
}
33+
}
34+
return map.values.find { it > 0 } == null
35+
*/
36+
37+
return IntArray(26).apply {
38+
for (index in s.indices) {
39+
this[s[index] - 'a'] = this[s[index] - 'a'] + 1
40+
this[t[index] - 'a'] = this[t[index] - 'a'] - 1
41+
}
42+
}.find { it > 0 } == null
43+
}
44+
45+
@Test
46+
fun `์ž…๋ ฅ๋ฐ›์€ ๋‘ ๋ฌธ์ž์—ด์ด ์• ๋„ˆ๊ทธ๋žจ์ด๋ผ๋ฉด ์ฐธ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค`() {
47+
isAnagram("anagram", "nagaram")
48+
isAnagram("test", "estt")
49+
}
50+
51+
@Test
52+
fun `์ž…๋ ฅ๋ฐ›์€ ๋‘ ๋ฌธ์ž์—ด์ด ์• ๋„ˆ๊ทธ๋žจ์ด ์•„๋‹ˆ๋ผ๋ฉด ๊ฑฐ์ง“์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค`() {
53+
isAnagram("cat", "rat")
54+
}
55+
}

0 commit comments

Comments
ย (0)