Skip to content

Commit 9a149b9

Browse files
authored
Merge pull request #643 from JisooPyo/main
[JisooPyo] Week 1
2 parents b8b7c86 + 920c9a9 commit 9a149b9

File tree

5 files changed

+370
-0
lines changed

5 files changed

+370
-0
lines changed

contains-duplicate/JisooPyo.kt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.shouldBe
4+
import org.junit.jupiter.api.Test
5+
6+
/**
7+
* Leetcode
8+
* 217. Contains Duplicate
9+
* Easy
10+
*/
11+
class ContainsDuplicate {
12+
/**
13+
* Runtime: 17 ms(Beats: 80.99 %)
14+
* Time Complexity: O(n)
15+
* - 배열 순회
16+
*
17+
* Memory: 50.63 MB(Beats: 70.32 %)
18+
* Space Complexity: O(n)
19+
* - HashSet에 최악의 경우 배열 원소 모두 저장
20+
*/
21+
fun containsDuplicate(nums: IntArray): Boolean {
22+
val set = hashSetOf<Int>()
23+
for (i in nums) {
24+
if (set.contains(i)) {
25+
return true
26+
}
27+
set.add(i)
28+
}
29+
return false
30+
}
31+
32+
@Test
33+
fun test() {
34+
containsDuplicate(intArrayOf(1, 2, 3, 1)) shouldBe true
35+
containsDuplicate(intArrayOf(1, 2, 3, 4)) shouldBe false
36+
containsDuplicate(intArrayOf(1, 1, 1, 3, 3, 4, 3, 2, 4, 2)) shouldBe true
37+
}
38+
}

house-robber/JisooPyo.kt

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.shouldBe
4+
import org.junit.jupiter.api.Test
5+
import kotlin.math.max
6+
7+
/**
8+
* Leetcode
9+
* 198. House Robber
10+
* Medium
11+
*
12+
* 사용된 알고리즘: Dynamic Programming
13+
*
14+
* i번째 집에서 얻을 수 있는 최대 금액은 다음 두 가지 중 큰 값입니다.
15+
* - (i-2)번째 집까지의 최대 금액 + 현재 집의 금액
16+
* - (i-1)번째 집까지의 최대 금액
17+
*/
18+
class HouseRobber {
19+
/**
20+
* Runtime: 0 ms(Beats: 100.00 %)
21+
* Time Complexity: O(n)
22+
*
23+
* Memory: 34.65 MB(Beats: 40.50 %)
24+
* Space Complexity: O(n)
25+
*/
26+
fun rob(nums: IntArray): Int {
27+
if (nums.size == 1) {
28+
return nums[0]
29+
}
30+
if (nums.size == 2) {
31+
return max(nums[0], nums[1])
32+
}
33+
val dp = IntArray(nums.size)
34+
dp[0] = nums[0]
35+
dp[1] = max(nums[0], nums[1])
36+
for (i in 2 until nums.size) {
37+
dp[i] = max(dp[i - 2] + nums[i], dp[i - 1])
38+
}
39+
return dp[nums.size - 1]
40+
}
41+
42+
/**
43+
* 공간 복잡도를 개선
44+
* Runtime: 0 ms(Beats: 100.00 %)
45+
* Time Complexity: O(n)
46+
*
47+
* Memory: 34.95 MB(Beats: 36.98 %)
48+
* Space Complexity: O(1)
49+
*/
50+
fun rob2(nums: IntArray): Int {
51+
if (nums.size == 1) return nums[0]
52+
if (nums.size == 2) return max(nums[0], nums[1])
53+
54+
var twoBack = nums[0]
55+
var oneBack = max(nums[0], nums[1])
56+
var current = oneBack
57+
58+
for (i in 2 until nums.size) {
59+
current = max(twoBack + nums[i], oneBack)
60+
twoBack = oneBack
61+
oneBack = current
62+
}
63+
64+
return current
65+
}
66+
67+
@Test
68+
fun test() {
69+
rob(intArrayOf(1, 2, 3, 1)) shouldBe 4
70+
rob(intArrayOf(2, 7, 9, 3, 1)) shouldBe 12
71+
rob2(intArrayOf(1, 2, 3, 1)) shouldBe 4
72+
rob2(intArrayOf(2, 7, 9, 3, 1)) shouldBe 12
73+
}
74+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.shouldBe
4+
import org.junit.jupiter.api.Test
5+
import kotlin.math.max
6+
7+
/**
8+
* Leetcode
9+
* 128. Longest Consecutive Sequence
10+
* Medium
11+
*/
12+
class LongestConsecutiveSequence {
13+
/**
14+
* Runtime: 58 ms(Beats: 79.06 %)
15+
* Time Complexity: O(n)
16+
* - while 루프의 총 반복 횟수는 n을 넘을 수 없다.
17+
*
18+
* Memory: 62.65 MB(Beats: 10.48 %)
19+
* Space Complexity: O(n)
20+
*/
21+
fun longestConsecutive(nums: IntArray): Int {
22+
val numsSet: MutableSet<Int> = nums.toHashSet()
23+
val startSet: MutableSet<Int> = hashSetOf()
24+
25+
// 수열의 시작점이 될 수 있는 수를 찾는다.
26+
for (num in numsSet) {
27+
if (!numsSet.contains(num - 1)) {
28+
startSet.add(num)
29+
}
30+
}
31+
var answer = 0
32+
for (start in startSet) {
33+
// 수열의 시작점부터 몇 개 까지 numsSet에 있는지 확인한다.
34+
var count = 0
35+
var first = start
36+
while (numsSet.contains(first)) {
37+
first++
38+
count++
39+
}
40+
// 최대 수열의 개수를 업데이트한다.
41+
answer = max(answer, count)
42+
}
43+
return answer
44+
}
45+
46+
/**
47+
* 위 풀이에서 startSet을 제거하여 공간적으로 효율적인 풀이
48+
* Runtime: 63 ms(Beats: 65.70 %)
49+
* Time Complexity: O(n)
50+
*
51+
* Memory: 58.47 MB(Beats: 70.81 %)
52+
* Space Complexity: O(n)
53+
*/
54+
fun longestConsecutive2(nums: IntArray): Int {
55+
val numsSet = nums.toHashSet()
56+
var maxLength = 0
57+
58+
for (num in numsSet) {
59+
if (!numsSet.contains(num - 1)) {
60+
var currentNum = num
61+
var currentLength = 0
62+
63+
while (numsSet.contains(currentNum)) {
64+
currentLength++
65+
currentNum++
66+
}
67+
maxLength = max(maxLength, currentLength)
68+
}
69+
}
70+
return maxLength
71+
}
72+
73+
@Test
74+
fun test() {
75+
longestConsecutive(intArrayOf(100, 4, 200, 1, 3, 2)) shouldBe 4
76+
longestConsecutive(intArrayOf(0, 3, 7, 2, 5, 8, 4, 6, 0, 1)) shouldBe 9
77+
78+
longestConsecutive2(intArrayOf(100, 4, 200, 1, 3, 2)) shouldBe 4
79+
longestConsecutive2(intArrayOf(0, 3, 7, 2, 5, 8, 4, 6, 0, 1)) shouldBe 9
80+
}
81+
}

top-k-frequent-elements/JisooPyo.kt

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.shouldBe
4+
import org.junit.jupiter.api.Test
5+
import java.util.*
6+
7+
/**
8+
* Leetcode
9+
* 347. Top K Frequent Elements
10+
* Medium
11+
*/
12+
class TopKFrequentElements {
13+
/**
14+
* Runtime: 30 ms(Beats: 68.62 %)
15+
* Time Complexity: O(n log n)
16+
* - list 정렬
17+
*
18+
* Memory: 42.20 MB(Beats: 58.82 %)
19+
* Space Complexity: O(n)
20+
*/
21+
fun topKFrequent(nums: IntArray, k: Int): IntArray {
22+
val countMap: MutableMap<Int, Int> = HashMap()
23+
24+
for (num in nums) {
25+
countMap[num] = countMap.getOrDefault(num, 0) + 1
26+
}
27+
28+
val list = mutableListOf<Node>()
29+
for (key in countMap.keys) {
30+
list.add(Node(key, countMap[key]!!))
31+
}
32+
list.sortDescending()
33+
34+
val answer = IntArray(k)
35+
for (i in 0 until k) {
36+
answer[i] = list[i].value
37+
}
38+
return answer
39+
}
40+
41+
/**
42+
* 개선된 버전: 우선순위 큐를 사용
43+
*
44+
* Runtime: 19 ms(Beats: 96.30 %)
45+
* Time Complexity: O(n log n)
46+
*
47+
* Memory: 44.83 MB(Beats: 18.35 %)
48+
* Space Complexity: O(n)
49+
*/
50+
fun topKFrequent2(nums: IntArray, k: Int): IntArray {
51+
val countMap = nums.groupBy { it }
52+
.mapValues { it.value.size }
53+
54+
val pq = PriorityQueue<Node>(compareByDescending { it.count })
55+
countMap.forEach { (num, count) ->
56+
pq.offer(Node(num, count))
57+
}
58+
59+
return IntArray(k) { pq.poll().value }
60+
}
61+
62+
data class Node(var value: Int, var count: Int) : Comparable<Node> {
63+
override fun compareTo(other: Node): Int {
64+
return this.count.compareTo(other.count)
65+
}
66+
}
67+
68+
@Test
69+
fun test() {
70+
topKFrequent(intArrayOf(1, 1, 1, 2, 2, 3), 2) shouldBe intArrayOf(1, 2)
71+
topKFrequent(intArrayOf(1), 1) shouldBe intArrayOf(1)
72+
73+
topKFrequent2(intArrayOf(1, 1, 1, 2, 2, 3), 2) shouldBe intArrayOf(1, 2)
74+
topKFrequent2(intArrayOf(1), 1) shouldBe intArrayOf(1)
75+
}
76+
}

valid-palindrome/JisooPyo.kt

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package leetcode_study
2+
3+
import io.kotest.matchers.shouldBe
4+
import org.junit.jupiter.api.Test
5+
6+
/**
7+
* Leetcode
8+
* 125. Valid Palindrome
9+
* Easy
10+
*/
11+
class ValidPalindrome {
12+
/**
13+
* Runtime: 4 ms(Beats: 98.27 %)
14+
* Time Complexity: O(n)
15+
*
16+
* Memory: 38.22 MB(Beats: 46.74 %)
17+
* Space Complexity: O(1)
18+
*/
19+
fun isPalindrome(s: String): Boolean {
20+
var left = 0
21+
var right = s.length - 1
22+
while (left <= right) {
23+
when (s[left]) {
24+
// 왼쪽의 문자가 alphanumeric일 때
25+
in 'a'..'z', in 'A'..'Z', in '0'..'9' -> {
26+
27+
when (s[right]) {
28+
// 오른쪽의 문자가 alphanumeric일 때
29+
in 'a'..'z', in 'A'..'Z', in '0'..'9' -> {
30+
// 문자 비교
31+
if (s[left].equals(s[right], true)) {
32+
left++
33+
right--
34+
continue
35+
} else {
36+
return false
37+
}
38+
}
39+
// 오른쪽의 문자가 alphanumeric이 아닐 때
40+
else -> {
41+
right--
42+
continue
43+
}
44+
}
45+
}
46+
47+
// 왼쪽의 문자가 alphanumeric이 아닐 때
48+
else -> {
49+
left++
50+
continue
51+
}
52+
}
53+
}
54+
return true
55+
}
56+
57+
/**
58+
* 개선한 버전
59+
* Runtime: 5 ms(Beats: 87.14 %)
60+
* Time Complexity: O(n)
61+
*
62+
* Memory: 37.76 MB(Beats: 61.52 %)
63+
* Space Complexity: O(1)
64+
*/
65+
fun isPalindrome2(s: String): Boolean {
66+
var left = 0
67+
var right = s.length - 1
68+
69+
while (left < right) {
70+
// 왼쪽에서 유효한 문자를 찾음
71+
while (left < right && !s[left].isLetterOrDigit()) {
72+
left++
73+
}
74+
75+
// 오른쪽에서 유효한 문자를 찾음
76+
while (left < right && !s[right].isLetterOrDigit()) {
77+
right--
78+
}
79+
80+
// 문자 비교
81+
if (!s[left].equals(s[right], ignoreCase = true)) {
82+
return false
83+
}
84+
85+
left++
86+
right--
87+
}
88+
return true
89+
}
90+
91+
@Test
92+
fun test() {
93+
isPalindrome("A man, a plan, a canal: Panama") shouldBe true
94+
isPalindrome("race a car") shouldBe false
95+
isPalindrome(" ") shouldBe true
96+
97+
isPalindrome2("A man, a plan, a canal: Panama") shouldBe true
98+
isPalindrome2("race a car") shouldBe false
99+
isPalindrome2(" ") shouldBe true
100+
}
101+
}

0 commit comments

Comments
 (0)