# 第 226 场周赛题解
# Q1 5654. 盒子中小球的最大数量 (opens new window)
直接暴力即可,Kotlin可以方便的通过sumBy直接计算和。
class Solution5654 {
fun countBalls(lowLimit: Int, highLimit: Int): Int {
val map = HashMap<Int, Int>()
for (i in lowLimit..highLimit) {
val k = i.toString().sumBy { it - '0' }
map[k] = map.getOrDefault(k, 0) + 1
}
return map.values.max()!!
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# Q2 5665. 从相邻元素对还原数组 (opens new window)
由于数组中的元素均不相同,因此只有数组头尾的元素仅出现一次,其余元素均会出现两次。找到头尾后,遍历查找下一个即可。
class Solution5665 {
fun restoreArray(adjacentPairs: Array<IntArray>): IntArray {
val map = HashMap<Int, ArrayList<Int>>()
adjacentPairs.forEach {
val (x, y) = it
map.getOrPut(x, { arrayListOf() }).add(y)
map.getOrPut(y, { arrayListOf() }).add(x)
}
val seen = HashSet<Int>()
val ans = arrayListOf<Int>()
fun dfs(i: Int) {
ans.add(i)
seen.add(i)
for (v in map[i]!!) {
if (v !in seen) {
dfs(v)
}
}
}
dfs(map.filter { it.value.size == 1 }.keys.first())
return ans.toIntArray()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Q3 5667. 你能在你最喜欢的那天吃到你最喜欢的糖果吗? (opens new window)
比赛过程中最恶心人的一道题!
- 注意天数是从0开始算,因此计算乘法时需要+1
- favoriteDay 和 dailyCap 均是10的9次方范围,直接使用Int会越界
根据前缀和,计算出糖果I的范围是[min, max]闭区间,而第day天可以吃到的糖果范围是[dayMin, dayMax],直接判断这两个区间是否有交集即可。
这种题在比赛时WA了很多次,各种边界条件判断不准确,这时候该冷静冷静,重新梳理下思路,使用最Simple的方法去解决。
class Solution5667 {
fun canEat(candiesCount: IntArray, queries: Array<IntArray>): BooleanArray {
val n = candiesCount.size
val preSum = LongArray(n + 1)
for (i in candiesCount.indices) {
preSum[i + 1] = preSum[i] + candiesCount[i]
}
val ans = ArrayList<Boolean>()
for (q in queries) {
val min = preSum[q[0]] + 1
val max = preSum[q[0] + 1]
val day = q[1]
val cap = q[2].toLong()
val dayMin = day + 1
val dayMax = (day + 1) * cap
ans.add(min <= dayMax && max >= dayMin)
}
return ans.toBooleanArray()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Q4 5666. 回文串分割 IV (opens new window)
先观察数据范围,长度只有2000,因此O(n²)的时间复杂度是可以接受的。
- 先计算出所有开头、结尾的是否是回文的二维数组isPal
- 找到以最后一个元素为结尾的,头部的index
- 遍历上述符合条件的index,开始查找以i为分割,能够使得(0, i) 和 (i + 1, index - 1)均为回文,则该字符串可以拆分为3个非空的回文字符串
class Solution5666 {
fun checkPartitioning(word: String): Boolean {
val n = word.length
val isPal = Array(n) { BooleanArray(n) }
for (i in 0 until n) {
for (j in 0..i) {
if (word[j] == word[i] && (i - j < 2 || isPal[j + 1][i - 1])) {
isPal[j][i] = true
}
}
}
val last = ArrayList<Int>()
for (i in 0 until n) {
if (isPal[i][n - 1]) last.add(i)
}
for (l in last) {
for (i in 0 until l) {
if (isPal[0][i] && isPal[i + 1][l - 1]) {
return true
}
}
}
return false
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25