# 第 51 场双周赛题解
# Q1 1844. 将所有数字用字符替换 (opens new window)
题目说不会超过,那就直接模拟就可以,不用考虑取余之类的。
时间复杂度:
class Solution1844 {
fun replaceDigits(s: String): String {
val ans = StringBuilder()
for (i in s.indices) {
if (i % 2 == 0) {
ans.append(s[i])
} else {
ans.append(s[i - 1] + (s[i] - '0'))
}
}
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 1845. 座位预约管理系统 (opens new window)
这时就用到了之前写的数据结构了,用二分的方法插入数据,并可随时返回最大值、最小值。
class SeatManager(n: Int) {
val set = MultiSet<Int>()
init {
for (i in 1..n) {
set.add(i)
}
}
fun reserve(): Int {
return set.popLeft()
}
fun unreserve(seatNumber: Int) {
set.add(seatNumber)
}
}
class MultiSet<T : Comparable<T>>(private val sumBy: (T) -> Int = { 0 }) {
private val valueList = ArrayList<T>()
private val countMap = HashMap<T, Int>()
var size = 0
var sum = 0L
val min: T
get() = valueList.first()
val max: T
get() {
return valueList.last()
}
fun add(value: T) {
val index = valueList.binarySearch(value)
if (index < 0) {
valueList.add(-index - 1, value)
countMap[value] = 1
} else {
countMap[value] = countMap[value]!! + 1
}
size++
sum += sumBy(value)
}
fun remove(value: T): Boolean {
if (value !in countMap.keys) return false
val index = valueList.binarySearch(value)
if (countMap[value] == 1) {
countMap.remove(value)
valueList.removeAt(index)
} else {
countMap[value] = countMap[value]!! - 1
}
size--
sum -= sumBy(value)
return true
}
fun popLeft(): T {
return valueList.first().also {
remove(it)
}
}
fun popRight(): T {
return valueList.last().also {
remove(it)
}
}
}
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# Q3 1846. 减小和重新排列数组后的最大元素 (opens new window)
理解题意后就好写了。首先排序,我们的操作只能减小值,排序后遍历,尽量使当前值尽可能的大,最终就会得到可能的最大元素。想通后感觉是个。
class Solution1846 {
fun maximumElementAfterDecrementingAndRearranging(arr: IntArray): Int {
arr.sort()
arr[0] = 1
for (i in 1 until arr.size) {
arr[i] = minOf(arr[i], arr[i - 1] + 1)
}
return arr.last()
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# Q4 1847. 最近的房间 (opens new window)
排序后离线操作即可,使用来存储房间号,最近的房间即和的结果,注意这里可能为空。因此需要一些防空的判断。
class Solution1847 {
fun closestRoom(rooms: Array<IntArray>, queries: Array<IntArray>): IntArray {
val ts = TreeSet<Int>()
var cur = 0
val ans = HashMap<String, Int>()
rooms.sortByDescending { it[1] }
val st = queries.sortedByDescending { it[1] }
st.forEach {
while (cur in rooms.indices && rooms[cur][1] >= it[1]) {
ts.add(rooms[cur][0])
cur++
}
val key = it.joinToString(",")
val a = ts.floor(it[0])
val b = ts.ceiling(it[0])
ans[key] = if (a == null && b == null) -1
else if (a == null) b!!
else if (b == null) a
else if (abs(a - it[0]) <= abs(b - it[0])) a
else b
}
return queries.map { ans[it.joinToString(",")]!! }.toIntArray()
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24