这次周赛依然只做出了三题:
T1-10min 2wa
T2-5min
T3-17min 1wa
复盘一下:
T1
https://leetcode.cn/problems/make-array-elements-equal-to-zero/
题面
给你一个整数数组 nums
。
开始时,选择一个满足 nums[curr] == 0
的起始位置 curr
,并选择一个移动 方向 :向左或者向右。
此后,你需要重复下面的过程:
- 如果
curr
超过范围[0, n - 1]
,过程结束。 - 如果
nums[curr] == 0
,沿当前方向继续移动:如果向右移,则 递增curr
;如果向左移,则 递减curr
。 - 如果
nums[curr] > 0
:- 将
nums[curr]
减 1 。 - 反转 移动方向(向左变向右,反之亦然)。
- 沿新方向移动一步。
如果在结束整个过程后,nums
中的所有元素都变为 0 ,则认为选出的初始位置和移动方向 有效 。
返回可能的有效选择方案数目。
- 将
1 <= nums.length <= 100
0 <= nums[i] <= 100
- 至少存在一个元素
i
满足nums[i] == 0
。
分析
由于数据量比较小,很多人都是模拟做的。但是模拟的代码也比较复杂,涉及到左右方向转换。所以可以找下规律,发现当nums[i] == 0
的时候,如果左右两边的数的和相等,那么就可以往两个方向任选一个方向走即可。于是直接这样写了,然后wa了。
其实还可以发现,当左右两边的数的和 suml和sumr,如果|suml - sumr| == 1
,那么也能成立,但是只能往大的一边走。
代码
1 | class Solution { |
T2
https://leetcode.cn/problems/zero-array-transformation-i/
题面
给定一个长度为 n
的整数数组 nums
和一个二维数组 queries
,其中 queries[i] = [li, ri]
。
对于每个查询 queries[i]
:
- 在
nums
的下标范围[li, ri]
内选择一个下标子集。 - 将选中的每个下标对应的元素值减 1。
零数组 是指所有元素都等于 0 的数组。
如果在按顺序处理所有查询后,可以将 nums
转换为 零数组 ,则返回 true
,否则返回 false
。
数组的 子集 是对数组元素的选择(可能为空)。
分析
差分数组模版题,每个位置都有对应操作完的最大值,如果数组该位置超过了最大阈值,则不成立。
代码
1 | class Solution { |
T3
https://leetcode.cn/problems/zero-array-transformation-ii/description/
题面
给你一个长度为 n
的整数数组 nums
和一个二维数组 queries
,其中 queries[i] = [li, ri, vali]
。
每个 queries[i]
表示在 nums
上执行以下操作:
- 将
nums
中[li, ri]
范围内的每个下标对应元素的值 最多 减少vali
。 - 每个下标的减少的数值可以独立选择。
零数组 是指所有元素都等于 0 的数组。
返回 k
可以取到的 最小****非负 值,使得在 顺序 处理前 k
个查询后,nums
变成 零数组。如果不存在这样的 k
,则返回 -1。
提示:
1 <= nums.length <= 105
0 <= nums[i] <= 5 * 105
1 <= queries.length <= 105
queries[i].length == 3
0 <= li <= ri < nums.length
1 <= vali <= 5
分析
二分答案+差分数组。
差分数组顾名思义,类似T2的操作,只是这里从加减1变成了常数。可以在o(1)时间内完成区间上加减定值。
由于k越大,越能满足题意,且题意为找一个最小的k,所以这一题的答案据有单调性,可以二份答案区间。这里其实k的取值可以是[1, m]
,所以右边界可以设置为 m + 1
。当最终得到m+1则证明没有valid答案。
这里二分枚举答案区间,如果在区间内就把右端点 r = mid; 如果不在区间内就把左断点 l = mid + 1;
代码
1 | class Solution { |
T4
TODO….