2025-06-12:零数组变换Ⅲ。用go语言,给定一个长度为 n 的整数数组 nums 和一个二维数组 queries,其中每
【摘要】 2025-06-12:零数组变换Ⅲ。用go语言,给定一个长度为 n 的整数数组 nums 和一个二维数组 queries,其中每个 queries[i] = [li, ri] 表示对 nums 的一个操作。每个操作表示:在索引范围 [li, ri] 内的元素,每个元素最多可以减少 1。需要注意的是,区间内每个元素减少的次数是独立计算的。定义“零数组”为所有元素均为 0 的数组。要求你找出最多...
2025-06-12:零数组变换Ⅲ。用go语言,给定一个长度为 n 的整数数组 nums 和一个二维数组 queries,其中每个 queries[i] = [li, ri] 表示对 nums 的一个操作。
每个操作表示:在索引范围 [li, ri] 内的元素,每个元素最多可以减少 1。需要注意的是,区间内每个元素减少的次数是独立计算的。
定义“零数组”为所有元素均为 0 的数组。
要求你找出最多可以从 queries 中删除多少个操作,使得剩下的操作仍然能够将 nums 减至零数组。如果无论如何都无法将 nums 变成零数组,则返回 -1。
1 <= nums.length <= 100000。
0 <= nums[i] <= 100000。
1 <= queries.length <= 100000。
queries[i].length == 2。
0 <= li <= ri < nums.length。
输入:nums = [1,1,1,1], queries = [[1,3],[0,2],[1,3],[1,2]]。
输出:2。
解释:
可以删除 queries[2] 和 queries[3] 。
题目来自力扣3362。
解题思路
-
贪心策略:
- 我们希望尽可能多地删除
queries
中的操作,因此应该优先保留那些覆盖范围更广(即[li, ri]
区间更长)的操作,因为它们可以同时对多个nums[i]
进行减 1 操作,减少对额外操作的需求。 - 因此,我们可以按照
li
(左端点)从小到大排序queries
,并在处理时优先选择ri
(右端点)较大的操作(使用最大堆)。
- 我们希望尽可能多地删除
-
差分数组优化:
- 直接对
nums
进行减 1 操作会导致时间复杂度较高(最坏情况 O(n²)),因此采用差分数组(deltaArray
)来记录每个位置需要减 1 的次数,从而在 O(1) 时间内完成区间更新。
- 直接对
-
处理流程:
- 排序
queries
:按li
从小到大排序,以便按顺序处理。 - 最大堆(优先队列):用于存储当前可用的
ri
(右端点),每次选择最大的ri
进行操作。 - 遍历
nums
:- 对于每个
nums[i]
,先应用差分数组的累计影响(即operations
)。 - 将所有
li == i
的queries
加入堆(表示这些操作当前可用)。 - 如果
nums[i]
还未减到 0,则从堆中取出最大的ri
进行操作(即operations++
,并在deltaArray[ri+1]
记录回退)。 - 如果
nums[i]
仍然无法减到 0,说明无法完成,返回-1
。
- 对于每个
- 最终,堆中剩余的操作就是可以删除的。
- 排序
详细步骤
-
预处理
queries
:- 按
li
从小到大排序,使得我们可以按顺序处理每个nums[i]
时,一次性加入所有li == i
的操作。
- 按
-
初始化数据结构:
- 差分数组
deltaArray
:长度为n+1
,用于记录区间操作的累计影响。 - 最大堆
pq
:存储当前可用的ri
(右端点),优先取最大的ri
。 - 操作计数器
operations
:记录当前nums[i]
已经减 1 的次数。
- 差分数组
-
遍历
nums
:- 对于每个
i
(从左到右):- 应用差分数组的影响:
operations += deltaArray[i]
。 - 将所有
li == i
的queries
加入堆(heap.Push(pq, ri)
)。 - 如果
nums[i] - operations > 0
(即还需要减 1),则从堆中取出最大的ri
:- 每取出一个
ri
,operations++
(表示对该区间[i, ri]
执行一次减 1)。 - 在
deltaArray[ri+1]--
(表示后续i > ri
时不再受此操作影响)。
- 每取出一个
- 如果
nums[i]
仍然无法减到 0,返回-1
。
- 应用差分数组的影响:
- 对于每个
-
返回结果:
- 最终堆中剩余的操作就是可以删除的,返回
pq.Len()
。
- 最终堆中剩余的操作就是可以删除的,返回
时间复杂度
- 排序
queries
:O(m log m),其中m
是queries
的长度。 - 堆操作:每个
queries[i]
最多入堆和出堆一次,每次堆操作 O(log m),总复杂度 O(m log m)。 - 遍历
nums
和差分数组处理:O(n + m)。 - 总时间复杂度:O(m log m + n + m) = O(m log m + n)。
空间复杂度
- 差分数组
deltaArray
:O(n)。 - 最大堆
pq
:O(m)。 - 总空间复杂度:O(n + m)。
Go完整代码如下:
.
package main
import (
"container/heap"
"fmt"
"sort"
)
func maxRemoval(nums []int, queries [][]int) int {
sort.Slice(queries, func(i, j int) bool {
return queries[i][0] < queries[j][0]
})
pq := &Heap{}
heap.Init(pq)
deltaArray := make([]int, len(nums)+1)
operations := 0
for i, j := 0, 0; i < len(nums); i++ {
operations += deltaArray[i]
for j < len(queries) && queries[j][0] == i {
heap.Push(pq, queries[j][1])
j++
}
for operations < nums[i] && pq.Len() > 0 && (*pq)[0] >= i {
operations += 1
deltaArray[heap.Pop(pq).(int)+1] -= 1
}
if operations < nums[i] {
return -1
}
}
return pq.Len()
}
type Heap []int
func (h Heap) Len() int {
return len(h)
}
func (h Heap) Less(i, j int) bool {
return h[i] > h[j]
}
func (h Heap) Swap(i, j int) {
h[i], h[j] = h[j], h[i]
}
func (h *Heap) Push(x interface{}) {
*h = append(*h, x.(int))
}
func (h *Heap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[0 : n-1]
return x
}
func main() {
nums := []int{1, 1, 1, 1}
queries := [][]int{{1, 3}, {0, 2}, {1, 3}, {1, 2}}
fmt.Println(maxRemoval(nums, queries))
}
Python完整代码如下:
.
# -*-coding:utf-8-*-
import heapq
def max_removal(nums, queries):
# 按左端点升序排序
queries.sort(key=lambda x: x[0])
pq = []
n = len(nums)
delta_array = [0] * (n + 1)
operations = 0
j = 0
for i in range(n):
operations += delta_array[i]
# 将左端点等于i的区间右端点加入堆,Python默认小顶堆,这里存入右端点,负号处理实现大顶堆
while j < len(queries) and queries[j][0] == i:
# 这里我们需要最大堆,而heapq是小顶堆,存入负值实现
heapq.heappush(pq, -queries[j][1])
j += 1
# 对应代码中,当operations < nums[i]且堆顶区间右端点大于等于 i,继续使用区间
while operations < nums[i] and pq and -pq[0] >= i:
operations += 1
end = -heapq.heappop(pq)
delta_array[end + 1] -= 1
if operations < nums[i]:
return -1
return len(pq)
if __name__ == "__main__":
nums = [1, 1, 1, 1]
queries = [[1, 3], [0, 2], [1, 3], [1, 2]]
print(max_removal(nums, queries))
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)