Skip to content

Commit bd6c112

Browse files
authored
Merge pull request #298 from jdalma/main
[์ •ํ˜„์ค€] 1์ฃผ์ฐจ ๋‹ต์•ˆ ์ œ์ถœ
2 parents 1a6b0f1 + 4fc8986 commit bd6c112

File tree

5 files changed

+381
-0
lines changed

5 files changed

+381
-0
lines changed

โ€Žcontains-duplicate/jdalma.kt

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.equals.shouldBeEqual
4+
import org.junit.jupiter.api.Test
5+
6+
class `contains-duplicate`{
7+
8+
fun containsDuplicate(nums: IntArray): Boolean {
9+
return usingSet(nums)
10+
}
11+
12+
// 1. ์ค‘์ฒฉ ๋ฐ˜๋ณต๋ฌธ - ์‹œ๊ฐ„์ดˆ๊ณผ
13+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(n^2), ๊ณต๊ฐ„๋ณต์žก๋„: O(1)
14+
private fun usingNestedLoop(nums: IntArray): Boolean {
15+
nums.forEachIndexed { i, e1 ->
16+
nums.forEachIndexed { j, e2 ->
17+
if (i != j && e1 == e2) {
18+
return true
19+
}
20+
}
21+
}
22+
return false
23+
}
24+
25+
// 2. ์ •๋ ฌ ํ›„ ์ˆœํšŒ
26+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(n * log(n)), ๊ณต๊ฐ„๋ณต์žก๋„: O(1)
27+
private fun usingSort(nums: IntArray): Boolean {
28+
nums.sort() // DualPivotQuicksort -> O(n log(n))
29+
for (index in 1 until nums.size) {
30+
val prev = nums[index - 1]
31+
val curr = nums[index]
32+
if (prev == curr) {
33+
return true
34+
}
35+
}
36+
return false
37+
}
38+
39+
// 3. ์ž๋ฃŒ๊ตฌ์กฐ Set ์‚ฌ์šฉ
40+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(n), ๊ณต๊ฐ„๋ณต์žก๋„: O(n)
41+
private fun usingSet(nums: IntArray): Boolean {
42+
val set = nums.toSet()
43+
return nums.size != set.size
44+
}
45+
46+
@Test
47+
fun ๋™์ผํ•œ_์›์†Œ๊ฐ€_์กด์žฌํ•˜๋ฉด_true๋ฅผ_๋ฐ˜ํ™˜ํ•œ๋‹ค() {
48+
val nums1 = intArrayOf(1, 2, 3, 1)
49+
val nums2 = intArrayOf(1, 2, 3, 2)
50+
val nums3 = intArrayOf(1, 1, 1, 1, 3, 3, 4, 3, 2, 4, 2)
51+
52+
containsDuplicate(nums1) shouldBeEqual true
53+
containsDuplicate(nums2) shouldBeEqual true
54+
containsDuplicate(nums3) shouldBeEqual true
55+
}
56+
57+
@Test
58+
fun ๋™์ผํ•œ_์›์†Œ๊ฐ€_์กด์žฌํ•˜์ง€_์•Š์œผ๋ฉด_false๋ฅผ_๋ฐ˜ํ™˜ํ•œ๋‹ค() {
59+
val nums1 = intArrayOf(1, 2, 3, 4)
60+
val nums2 = intArrayOf(1, 5, 7)
61+
62+
containsDuplicate(nums1) shouldBeEqual false
63+
containsDuplicate(nums2) shouldBeEqual false
64+
}
65+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.equals.shouldBeEqual
4+
import org.junit.jupiter.api.Test
5+
import java.util.PriorityQueue
6+
7+
class `kth-smallest-element-in-a-bst` {
8+
9+
fun kthSmallest(root: TreeNode?, k: Int): Int {
10+
return inorderTraversal(root, k)
11+
}
12+
13+
// 1. ์žฌ๊ท€ ํ˜ธ์ถœ๋กœ ๋ชจ๋“  ํŠธ๋ฆฌ๋ฅผ ์กฐํšŒ ํ›„ ์ •๋ ฌ
14+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(n * log(n)), ๊ณต๊ฐ„๋ณต์žก๋„: O(n)
15+
private fun recursionAndSort(root: TreeNode?, k: Int) = mutableSetOf<Int>().apply {
16+
dfs(root, this)
17+
}.sorted()[k - 1]
18+
19+
private fun dfs(node: TreeNode?, set: MutableSet<Int>) {
20+
if (node == null) return
21+
22+
set.add(node.`val`)
23+
dfs(node.left, set)
24+
dfs(node.right, set)
25+
}
26+
27+
// 2. ์žฌ๊ท€ ํ˜ธ์ถœ๋กœ ๋ชจ๋“  ํŠธ๋ฆฌ์˜ ๊ฐ’์„ ์šฐ์„ ์ˆœ์œ„ ํ์— ์‚ฝ์ž…ํ•˜๊ณ  ์ž‘์€ ๊ฐ’์œผ๋กœ ๊ณ„์† ํ๋ฅผ ๊ฐฑ์‹ 
28+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(n * log(k)), ๊ณต๊ฐ„๋ณต์žก๋„: O(n + k)
29+
// ํŠธ๋ฆฌ ์ˆœํšŒ : O(n), ์šฐ์„ ์ˆœ์œ„ ํ ์‚ฝ์ž…: O(log k)
30+
private fun usingPriorityQueue(node: TreeNode?, k: Int): Int {
31+
fun dfs(node: TreeNode, k: Int, pq: PriorityQueue<Int>) {
32+
pq.offer(node.`val`)
33+
34+
if (pq.size > k) {
35+
pq.poll()
36+
}
37+
if (node.left != null) {
38+
dfs(node.left!!, k, pq)
39+
}
40+
if (node.right != null) {
41+
dfs(node.right!!, k, pq)
42+
}
43+
}
44+
45+
val pq = PriorityQueue { v1: Int, v2: Int -> v2 - v1 }
46+
dfs(node!!, k, pq)
47+
return pq.first()
48+
}
49+
50+
// 3. ๋ฌธ์ œ์˜ ์ „์ œ๊ฐ€ ์ด์ง„ํƒ์ƒ‰ํŠธ๋ฆฌ์ด๊ธฐ์—, ์ค‘์œ„์ˆœํšŒ๋กœ ํƒ์ƒ‰ํ•˜์—ฌ ๊ฐ’์„ ๋ˆ„์ ํ•˜๋ฉด ์˜ค๋ฆ„์ฐจ์ˆœ์˜ ๊ฐ’์ด ๋œ๋‹ค.
51+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(n), ๊ณต๊ฐ„๋ณต์žก๋„: O(n)
52+
private fun inorderTraversal(node: TreeNode?, k: Int): Int {
53+
fun dfs(node: TreeNode, k: Int, list: MutableList<Int>) {
54+
if (node.left != null) {
55+
dfs(node.left!!, k, list)
56+
}
57+
list.add(node.`val`)
58+
if (node.right != null) {
59+
dfs(node.right!!, k, list)
60+
}
61+
}
62+
63+
return mutableListOf<Int>().apply {
64+
dfs(node!!, k, this)
65+
}[k - 1]
66+
}
67+
68+
@Test
69+
fun `๋ฃจํŠธ์™€ ์ •์ˆ˜ k๊ฐ€ ์ฃผ์–ด์ง€๋ฉด ํŠธ๋ฆฌ์— ์žˆ๋Š” ๋ชจ๋“  ๋…ธ๋“œ์˜ ๊ฐ’ ์ค‘ ๊ฐ€์žฅ ์ž‘์€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค`() {
70+
kthSmallest(TreeNode.of(listOf(0, 3,1,4,null,2)), 1) shouldBeEqual 1
71+
kthSmallest(TreeNode.of(listOf(0, 5,3,6,2,4,null,null,1)), 3) shouldBeEqual 3
72+
}
73+
}
74+
75+
class TreeNode(var `val`: Int) {
76+
var left: TreeNode? = null
77+
var right: TreeNode? = null
78+
79+
companion object {
80+
fun of(numbers: List<Int?>): TreeNode? {
81+
fun setChild(node: TreeNode?, nums: List<Int?>, index: Int): TreeNode? {
82+
if (node == null) return null
83+
val (leftIndex, rightIndex) = index * 2 to index * 2 + 1
84+
85+
if (leftIndex < nums.size && nums[leftIndex] != null) {
86+
node.left = TreeNode(nums[leftIndex]!!)
87+
setChild(node.left, nums, leftIndex)
88+
}
89+
if (rightIndex < nums.size && nums[rightIndex] != null) {
90+
node.right = TreeNode(nums[rightIndex]!!)
91+
setChild(node.right, nums, rightIndex)
92+
}
93+
return node
94+
}
95+
return setChild(TreeNode(numbers[1]!!), numbers, 1)
96+
}
97+
}
98+
}

โ€Žnumber-of-1-bits/jdalma.kt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.equals.shouldBeEqual
4+
import org.junit.jupiter.api.Test
5+
6+
class `number-of-1-bits` {
7+
8+
fun hammingWeight(n: Int): Int {
9+
return bitOperation(n)
10+
}
11+
12+
// 1. ์ง์ ‘ 2์ง„์ˆ˜๋ฅผ ๊ตฌํ•จ
13+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(log n), ๊ณต๊ฐ„๋ณต์žก๋„: O(1)
14+
private fun binary(n: Int): Int {
15+
var calc = n
16+
var count = 0
17+
while(calc > 0) {
18+
if (calc % 2 != 0) {
19+
count++
20+
}
21+
calc /= 2
22+
}
23+
return count
24+
}
25+
26+
// 2. ๋น„ํŠธ ๋…ผ๋ฆฌ ์—ฐ์‚ฐ์ž ์‚ฌ์šฉ
27+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(log n), ๊ณต๊ฐ„๋ณต์žก๋„: O(1)
28+
private fun bitOperation(n: Int): Int {
29+
var calc = n
30+
var count = 0
31+
while (calc > 0) {
32+
if (calc and 1 == 1) {
33+
count ++
34+
}
35+
calc = calc shr 1
36+
}
37+
return count
38+
}
39+
40+
@Test
41+
fun `์ด์ง„์ˆ˜์—์„œ_0์ด_์•„๋‹Œ_์„ฑ๋ถ„์˜_๊ฐœ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค`() {
42+
hammingWeight(11) shouldBeEqual 3
43+
hammingWeight(128) shouldBeEqual 1
44+
hammingWeight(2147483645) shouldBeEqual 30
45+
}
46+
}

โ€Žpalindromic-substrings/jdalma.kt

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.equals.shouldBeEqual
4+
import org.junit.jupiter.api.Test
5+
6+
class `palindromic-substrings` {
7+
8+
fun countSubstrings(s: String): Int {
9+
return dp(s)
10+
}
11+
12+
// 1. ๋ธŒ๋ฃจํŠธํฌ์Šค 3์ค‘ ๋ฐ˜๋ณต๋ฌธ
13+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(n^3), ๊ณต๊ฐ„๋ณต์žก๋„: O(1)
14+
private fun bruteForce(s: String): Int {
15+
16+
fun isPalindrome(text: String, left: Int, right: Int): Boolean {
17+
var (start, end) = left to right
18+
while (start < end) {
19+
if (text[start] != text[end]) {
20+
return false
21+
}
22+
start++
23+
end--
24+
}
25+
return true
26+
}
27+
28+
var count = 0
29+
s.indices.forEachIndexed { left, _ ->
30+
(left until s.length).forEach { right ->
31+
if (isPalindrome(s, left, right)) {
32+
count++
33+
}
34+
}
35+
}
36+
return count
37+
}
38+
39+
// 2. ๋ฌธ์ž์—ด์˜ ๊ธธ์ด๊ฐ€ ํ™€์ˆ˜,์ง์ˆ˜๋ฅผ ๊ฐ์•ˆํ•˜์—ฌ ํŠน์ • ์ง€์ ๋ถ€ํ„ฐ ๋‘ ๊ฐœ์˜ ํฌ์ธํ„ฐ left , right๋ฅผ ๋น„๊ตํ•œ๋‹ค.
40+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(n^2), ๊ณต๊ฐ„๋ณต์žก๋„: O(1)
41+
private fun twoPointer(s: String): Int {
42+
43+
fun palindromeCount(text: String, left: Int, right: Int): Int {
44+
var count = 0
45+
var (l , r) = left to right
46+
while (l >= 0 && r < text.length && text[l--] == text[r++]) {
47+
count++
48+
}
49+
return count
50+
}
51+
52+
var result = 0
53+
s.indices.forEachIndexed { index, e ->
54+
val even = palindromeCount(s, index, index + 1)
55+
val odd = palindromeCount(s, index - 1, index + 1)
56+
result += even + odd + 1
57+
}
58+
59+
return result
60+
}
61+
62+
// 3. DP : ์ด์ „์— ๋น„๊ตํ–ˆ๋˜ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ์–ตํ•˜์—ฌ (ํ˜„์žฌ ์ฃผ์–ด์ง„ start, end ๋น„๊ต) && (์ด์ „ start, end ๋น„๊ต)
63+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(n^2), ๊ณต๊ฐ„๋ณต์žก๋„: O(n^2)
64+
private fun dp(s: String): Int {
65+
val len = s.length
66+
val dp = Array(len) { BooleanArray(len) { false } }
67+
68+
for (end in 0 until len) {
69+
for (start in end downTo 0) {
70+
if (start == end) {
71+
dp[start][end] = true
72+
} else if (start + 1 == end) {
73+
dp[start][end] = s[start] == s[end]
74+
} else {
75+
dp[start][end] = s[start] == s[end] && dp[start + 1][end - 1]
76+
}
77+
}
78+
}
79+
80+
return dp.sumOf { row -> row.count { it } }
81+
}
82+
83+
@Test
84+
fun `์ฃผ์–ด์ง„ ๋ฌธ์ž์—ด์˜ ํšŒ๋ฌธ์ธ ๋ถ€๋ถ„ ๋ฌธ์ž์—ด์˜ ๊ฐœ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค`() {
85+
countSubstrings("abc") shouldBeEqual 3
86+
countSubstrings("aaa") shouldBeEqual 6
87+
countSubstrings("ababa") shouldBeEqual 9
88+
countSubstrings("abcda") shouldBeEqual 5
89+
}
90+
}

โ€Žtop-k-frequent-elements/jdalma.kt

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.shouldBe
4+
import org.junit.jupiter.api.Test
5+
import java.util.PriorityQueue
6+
7+
class `top-k-frequent-elements` {
8+
9+
fun topKFrequent(nums: IntArray, k: Int): IntArray {
10+
return third(nums, k)
11+
}
12+
13+
// 1. Map ์ •๋ ฌ
14+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(n * log(n)), ๊ณต๊ฐ„๋ณต์žก๋„: O(n)
15+
private fun first(nums: IntArray, k: Int): IntArray {
16+
val map = mutableMapOf<Int, Int>()
17+
18+
nums.forEach {
19+
map.compute(it) { _, oldValue ->
20+
if (oldValue == null) 1
21+
else oldValue + 1
22+
}
23+
}
24+
25+
return map.entries.sortedByDescending { it.value }
26+
.map { it.key }
27+
.slice(0 until k)
28+
.toIntArray()
29+
}
30+
31+
// 2. ์šฐ์„ ์ˆœ์œ„ ํ
32+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(n * log(k)), ๊ณต๊ฐ„๋ณต์žก๋„: O(n + k)
33+
private fun second(nums: IntArray, k: Int): IntArray {
34+
val map = mutableMapOf<Int, Int>()
35+
36+
nums.forEach { map.put(it, map.getOrDefault(it, 0) + 1) }
37+
38+
val heap: PriorityQueue<Map.Entry<Int, Int>> = PriorityQueue<Map.Entry<Int, Int>> {
39+
v1, v2 -> v2.value.compareTo(v1.value)
40+
}.apply {
41+
this.addAll(map.entries)
42+
}
43+
44+
return (0 until k).map { heap.poll().key }.toIntArray()
45+
}
46+
47+
// 3. ์ด์ฐจ์›๋ฐฐ์—ด๋กœ ๋นˆ๋ฒˆ๋„ ์ €์žฅ
48+
// ์‹œ๊ฐ„๋ณต์žก๋„: O(n), ๊ณต๊ฐ„๋ณต์žก๋„: O(n)
49+
private fun third(nums: IntArray, k: Int): IntArray {
50+
val map = mutableMapOf<Int, Int>()
51+
52+
nums.forEach { map.put(it, map.getOrDefault(it, 0) + 1) }
53+
54+
val freq = Array<MutableList<Int>>(nums.size + 1) { mutableListOf() }
55+
map.entries.forEach {
56+
val frequency = it.value
57+
freq[frequency].add(it.key)
58+
}
59+
60+
val result = IntArray(k)
61+
var index = 0
62+
(freq.size - 1 downTo 0).forEach { i ->
63+
freq[i].forEach {
64+
result[index++] = it
65+
if (index == k) {
66+
return result
67+
}
68+
}
69+
}
70+
71+
return IntArray(0)
72+
}
73+
74+
@Test
75+
fun `๋ฐฐ์—ด์—์„œ_๊ฐ€์žฅ_๋นˆ๋„๊ฐ€_๋†’์€_K๊ฐœ์˜_์›์†Œ๋ฅผ_์ถœ๋ ฅํ•œ๋‹ค`() {
76+
topKFrequent(intArrayOf(1,1,1,2,2,3), 2) shouldBe intArrayOf(1,2)
77+
topKFrequent(intArrayOf(1,1,1,2,2,3,3,4), 3) shouldBe intArrayOf(1,2,3)
78+
topKFrequent(intArrayOf(2,2,3,3,1,1,4), 3) shouldBe intArrayOf(2,3,1)
79+
topKFrequent(intArrayOf(4,1,-1,2,-1,2,3), 2) shouldBe intArrayOf(-1,2)
80+
81+
}
82+
}

0 commit comments

Comments
ย (0)