leetcode 3542. 将所有元素变为 0 的最少操作次数 中等
给你一个大小为 n 的 非负 整数数组 nums 。你的任务是对该数组执行若干次(可能为 0 次)操作,使得 所有 元素都变为 0。
在一次操作中,你可以选择一个子数组 [i, j](其中 0 <= i <= j < n),将该子数组中所有 最小的非负整数 的设为 0。
返回使整个数组变为 0 所需的最少操作次数。
一个 子数组 是数组中的一段连续元素。
示例 1:
输入: nums = [0,2]
输出: 1
解释:
- 选择子数组
[1,1](即[2]),其中最小的非负整数是 2。将所有 2 设为 0,结果为[0,0]。 - 因此,所需的最少操作次数为 1。
示例 2:
输入: nums = [3,1,2,1]
输出: 3
解释:
- 选择子数组
[1,3](即[1,2,1]),最小非负整数是 1。将所有 1 设为 0,结果为[3,0,2,0]。 - 选择子数组
[2,2](即[2]),将 2 设为 0,结果为[3,0,0,0]。 - 选择子数组
[0,0](即[3]),将 3 设为 0,结果为[0,0,0,0]。 - 因此,最少操作次数为 3。
示例 3:
输入: nums = [1,2,1,2,1,2]
输出: 4
解释:
- 选择子数组
[0,5](即[1,2,1,2,1,2]),最小非负整数是 1。将所有 1 设为 0,结果为[0,2,0,2,0,2]。 - 选择子数组
[1,1](即[2]),将 2 设为 0,结果为[0,0,0,2,0,2]。 - 选择子数组
[3,3](即[2]),将 2 设为 0,结果为[0,0,0,0,0,2]。 - 选择子数组
[5,5](即[2]),将 2 设为 0,结果为[0,0,0,0,0,0]。 - 因此,最少操作次数为 4。
提示:
1 <= n == nums.length <= 10^50 <= nums[i] <= 10^5
分析:想要得到最少的操作次数,每次都把最长的非 0 区间内的最小值都变成 0,重复进行这样的操作,直到所有的数字都变为 0 就是答案。但是由于数字的数量 n 范围有 10 的 5 次方,因此暴力的方法是不行的。
可以用单调栈的方法来解决这道题。设答案为 ans,遍历整个 nums 数组,不妨设当前栈顶的元素为 top,当前遍历到的元素为 nums[i],值等于 a。首先要检查 a 的值是否小于或等于 top,如果是,则说明 a 应该会同时,或者先比 top 变为 0,此时要一直出栈,直到栈为空,或者 top 大于 a 为止。接着如果 a 为 0,则直接跳过,因为 0 本身不用做任何操作。如果 a 不为零,且栈为空,或者 a 的值大于 top,说明使 a 变为 0 的操作一定在 top 变为 0 的操作之后,此时将 a 压入栈,操作次数 ans++。遍历完成后,返回 ans 的值。
int minOperations(int* nums, int numsSize) {int ans=0,t=0;int stack[numsSize+5];for(int i=0;i<numsSize;++i){while(t>0&&nums[i]<stack[t-1])t--;if(nums[i]==0)continue;if(!t||nums[i]>stack[t-1])stack[t]=nums[i],t++,ans++;}return ans;
}