leetcode每日一题 -- 3362. 零数组变换 III
思路
题意是要找出[最少的区间]使nums数组变为零数组,并且使用的区间可以不连续
- 我的第一想法是先给区间按照左边界排序(就像区间合并题的准备工作那样)
- 这样的可以使用最大堆,每次将右区间值最大(也就是区间范围最大)的区间应用到差分数组中
- 但是,后续如何处理还是不太会,遂看了题解,以下是以题解代码作出的思考
预处理思路是一样的,而后续的处理方式是以nums中每个数字为基准,完成一个核心逻辑后,就判断当前累加值是否能将当前数字清为0
核心逻辑:
贪心+大堆
以i为基准值,将queries以左区间值为标准分为多组,每次插入一组
- 插入右区间值到大堆中,因为我们要先拿到范围最大的区间
记录一个累加值
- 类似于之前初始化好差分数组后的计算前缀和
- 后续使用区间时,也要+1 -- 相当于多了一个区间可以对当前位置操作(-1),而这里的+1就代表了传统差分数组中对左区间+1的操作
接下来就是将有效区间应用到差分数组中,并且处理右区间
- 有效区间 -- 因为有可能在上个步骤中剩余了区间,导致右区间 < 此时的i
- 当使用完一个区间后,就把它出队,最终还在大堆中的就是未使用的区间(删除的区间)
代码
class Solution {
public:int maxRemoval(vector<int>& nums, vector<vector<int>>& queries) {// 最先找到范围大的区间(比较右边界),左边界可以从0开始遍历sort(queries.begin(), queries.end(),[](const vector<int>& x, const vector<int>& y) {return x[0] < y[0];});int n = nums.size();vector<int> delt_arr(n + 1, 0);int op_num = 0;priority_queue<int> heap; // 默认大堆// 比较当前每一位数字是否可以被减为0for (int i = 0, j = 0; i < nums.size(); ++i) {// 累加出当前可以被操作的值op_num += delt_arr[i];// 每次加入左区间为i的数组while (j < queries.size() && queries[j][0] == i) {heap.push(queries[j][1]);++j;}// 经大堆排序后,初始化到差分数组中(注意,这里插入的要是有效区间)while (op_num < nums[i] && heap.size() > 0 && heap.top() >= i) {// 有一个新区间覆盖到当前位置op_num++;delt_arr[heap.top() + 1]--;heap.pop();}// 所有覆盖到该位的区间都已操作完if (op_num < nums[i]) {return -1;}}return heap.size();}
};