# 第 240 场周赛题解
# Q1 1854. 人口最多的年份 (opens new window)
该题若是没有给出范围 or 范围较大,则需要使用差分数组来处理。而真正给出的范围较小,因此直接暴力即可。
class Solution1854 {
fun maximumPopulation(logs: Array<IntArray>): Int {
var max = 0
var ans = -1
for (i in 1950..2050) {
val cnt = logs.count { it[0] <= i && it[1] - 1 >= i }
if (cnt > max) {
max = cnt
ans = i
}
}
return ans
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# Q2 1855. 下标对中的最大距离 (opens new window)
简单的双指针操作,时间复杂度为。
class Solution1855 {
fun maxDistance(nums1: IntArray, nums2: IntArray): Int {
var ans = 0
var i = 0
var j = 0
while (i in nums1.indices && j in nums2.indices) {
j = maxOf(j, i)
while (j in nums2.indices && nums2[j] >= nums1[i]) {
ans = maxOf(ans, j - i)
j++
}
i++
}
return ans
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Q3 1856. 子数组最小乘积的最大值 (opens new window)
比赛时没做出来,还要加强学习!
可以以每个元素为最小值,向左向右查到最远距离。这个查找如果用暴力,时间复杂度为,会超时。可以使用两个单调栈分别求出左侧、右侧的下标,将时间复杂度降低为。
class Solution5752 {
fun maxSumMinProduct(nums: IntArray): Int {
val mod = 1000000007L
val preSum = LongArray(nums.size + 1)
for (i in nums.indices) {
preSum[i + 1] = preSum[i] + nums[i]
}
val rightSmall = IntArray(nums.size) { nums.size }
val leftSmall = IntArray(nums.size) { -1 }
val stack = Stack<Int>()
for (i in nums.indices) {
while (stack.isNotEmpty() && nums[i] < nums[stack.peek()]) {
rightSmall[stack.pop()] = i
}
stack.push(i)
}
stack.clear()
for (i in nums.indices.reversed()) {
while (stack.isNotEmpty() && nums[i] < nums[stack.peek()]) {
leftSmall[stack.pop()] = i
}
stack.push(i)
}
var ans = 0L
for (i in nums.indices) {
val left = leftSmall[i]
val right = rightSmall[i]
ans = maxOf(ans, nums[i] * (preSum[right] - preSum[left + 1]))
}
return (ans % mod).toInt()
}
}
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
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
# Q4 1857. 有向图中最大颜色值 (opens new window)
比赛时,写完了图的拓扑排序,之后使用正向查找,会超时...
需要使用进行逆向查找,并且每次查找中的一个,降低了时间复杂度,为。
class Solution1857 {
fun largestPathValue(colors: String, edges: Array<IntArray>): Int {
val n = colors.length
val g = Graph(n)
edges.forEach {
g.addEdgeOri(it[0], it[1])
}
val arr = g.topologicalSort()
if (arr.isEmpty()) return -1
arr.reverse()
var ans = 0
for (i in 'a'..'z') {
val dp = IntArray(n)
for (j in arr.indices) {
for (k in g.adj[arr[j]]) {
dp[arr[j]] = maxOf(dp[arr[j]], dp[k])
}
dp[arr[j]] += if (colors[arr[j]] == i) 1 else 0
ans = maxOf(ans, dp[arr[j]])
}
}
return ans
}
}
class Graph(val n: Int) {
// 图中边(可以有方向)
var adj: Array<LinkedList<Int>> = Array(n) { LinkedList<Int>() }
// 图中边的权重(可以有方向)
val weight = HashMap<Int, HashMap<Int, Int>>()
init {
for (i in 0 until n) {
weight[i] = hashMapOf()
}
}
fun addEdgeOri(i: Int, j: Int, w: Int = 0) {
adj[i].add(j)
weight[i]!![j] = w
}
fun addEdge(i: Int, j: Int, w: Int = 0) {
// Add w to v's list.
adj[i].add(j)
// Add v to w's list
adj[j].add(i)
weight[i]!![j] = w
weight[j]!![i] = w
}
}
// prints a Topological Sort of the complete graph
fun Graph.topologicalSort(): ArrayList<Int> {
// Create a array to store indegrees of all
// vertices. Initialize all indegrees as 0.
val indegree = IntArray(n)
// Traverse adjacency lists to fill indegrees of
// vertices. This step takes O(V+E) time
for (i in 0 until n) {
val temp = adj[i]
for (node in temp) {
indegree[node]++
}
}
// Create a queue and enqueue all vertices with
// indegree 0
val q: Queue<Int> = PriorityQueue<Int>() { a, b ->
indegree[b] - indegree[a]
}
for (i in 0 until n) {
if (indegree[i] == 0)
q.add(i)
}
// Initialize count of visited vertices
var cnt = 0
// Create a vector to store result (A topological
// ordering of the vertices)
val topOrder = ArrayList<Int>()
while (!q.isEmpty()) {
// Extract front of queue (or perform dequeue)
// and add it to topological order
val u = q.poll()
topOrder.add(u)
// Iterate through all its neighbouring nodes
// of dequeued node u and decrease their in-degree
// by 1
for (node in adj[u]) {
// If in-degree becomes zero, add it to queue
if (--indegree[node] == 0)
q.add(node)
}
cnt++
}
// Check if there was a cycle
if (cnt != n) {
println("There exists a cycle in the graph")
return arrayListOf()
}
val ans = arrayListOf<Int>()
// Print topological order
for (i in topOrder) {
ans.add(i)
}
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
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115