# 第 58 场双周赛题解
# Q1 1957. 删除字符使字符串变好 (opens new window)
正常遍历,第三个重复的就要删掉。
class Solution5193 {
fun makeFancyString(s: String): String {
val ans = StringBuilder()
s.forEach {
if (ans.length < 2)
ans.append(it)
else if (ans[ans.length - 1] != it || ans[ans.length - 2] != it) {
ans.append(it)
}
}
return ans.toString()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# Q2 1958. 检查操作是否合法 (opens new window)
麻烦的题目,正常按题意模拟即可。
class Solution5827 {
fun checkMove(board: Array<CharArray>, rMove: Int, cMove: Int, color: Char): Boolean {
val dir8 = arrayOf(
intArrayOf(0, 1),
intArrayOf(1, 1),
intArrayOf(-1, 1),
intArrayOf(0, -1),
intArrayOf(1, -1),
intArrayOf(-1, -1),
intArrayOf(1, 0),
intArrayOf(-1, 0)
)
fun dfs(it: Int): Boolean {
val ori = dir8[it]
var r = rMove
var c = cMove
var seen = false
while (r + ori[0] in 0..7 && c + ori[1] in 0..7) {
r += ori[0]
c += ori[1]
// println("$r $c")
when (board[r][c]) {
'.' -> return false
color -> return seen
else -> seen = true
}
}
return false
}
repeat(8) {
if (dfs(it)) 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
26
27
28
29
30
31
32
33
34
35
36
37
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# Q3 1959. K 次调整数组大小浪费的最小总空间 (opens new window)
相当可以的题目,这题是标准的啊,给个就离谱!
首先求出范围内的浪费值,即范围内的最大值与的乘积减去真实的。下面就可以用进行处理了。
设为第次调整后,前位的浪费值:
class Solution5828 {
fun minSpaceWastedKResizing(nums: IntArray, k: Int): Int {
val n = nums.size
// 获取[i..j]范围内 最大值*count 减去 sum 的二维数组
val cost = Array<IntArray>(nums.size) { IntArray(nums.size) }
for (i in nums.indices) {
var cur = nums[i]
var sum = nums[i]
for (j in i + 1 until nums.size) {
cur = maxOf(cur, nums[j])
sum += nums[j]
cost[i][j] = cur * (j - i + 1) - sum
}
}
val dp = Array<IntArray>(n) { IntArray(k + 2) { Int.MAX_VALUE / 2 } }
for (j in 1..k + 1) {
for (i in 0 until n) {
// 第l位开始转移的最小值
for (l in 0..i) {
// 第j次转移,前i个值的浪费最小值
dp[i][j] = minOf(dp[i][j], (if (l == 0) 0 else dp[l - 1][j - 1]) + cost[l][i])
}
}
}
return dp[n - 1][k + 1]
}
}
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
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# Q4 1960. 两个回文子字符串长度的最大乘积 (opens new window)
首先,通过算法将中心扩展的最长回文半径求出来。
之后,将以为右边界和为左边界的最长回文长度求出来,利用前缀数组即可。
以为分割点,求出最大值。第一个回文串右边界,第二个回文串左边界从,不会有交集。
class Solution5220 {
// 回文字符串
// 马拉车算法
fun maxProduct(s: String): Long {
val n = s.length
val len = manacher(s)
val left = LongArray(n) { 1 }
var p = 0
for (i in 1 until n) {
// 以i为右边界的最长回文长度
while (p + len[p] < i) p++
left[i] = maxOf(left[i - 1], 1L + 2L * (i - p))
}
val right = LongArray(n) { 1 }
p = n - 1
for (i in n - 2 downTo 0) {
// 以i为左边界的最长回文长度
while (p - len[p] > i) p--
right[i] = maxOf(right[i + 1], 1L + 2L * (p - i))
}
var ans = 1L
for (i in 0 until n - 1) {
ans = maxOf(ans, left[i] * right[i + 1])
}
return ans
}
}
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
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27