3542. Minimum Operations to Convert All Elements to Zero
题目简介
/**
* @param {number[]} nums
* @return {number}
*/
本题给我们一个数字数组 nums,要求我们经过一系列操作之后,把 nums 数组全部元素变为 0
题目要求我们求最少要多少次操作
每次操作我们都需要选择任意子数组,然后将子数组中最小的元素置为 0
解题思路
根据题目所述,我们的最优解法就是:
- 把整个数组当成子数组,然后把最小的元素全部置为 0
- 把剩下的数组从 0 的位置分为多个子数组,然后分别执行第一步
- 如果整个数组都为 0 了就终止操作
根据上述思路,我们可以再进一步思考一下,该如何简化
我们使用 [1, 2, 3, 2, 3] 这个例子来解释:
- 首先考虑单调递增的情况,也就是开头的
[1, 2, 3]这种情况我们不难看出需要三次的操作 - 紧接着我们多考虑一位:
[1, 2, 3, 2]这种情况依然需要三次操作 - 下一步:
[1, 2, 3, 2, 3]这次需要四次操作
看出区别了吗?只要是后面一位比前一位大,我们都是需要进行额外的操作的
那么问题就变成了,我们要如何记录上一位的数字大小呢?
我们可以使用一个栈 stack ,以下是步骤说明:
- 由于前三位是递增,我们将其依序入栈,此时
stack = [1, 2, 3],需要的操作为 3 次 - 第四位出现了 2,比当前的栈顶 3 小,所以我们需要把当前栈顶依序出栈直到当前栈顶小于等于 2,操作次数不变
- 第五位出现了 3,此时栈顶为 2,我们需要把 3 入栈,操作数也需要加一,此时为 4
- 数组遍历完毕,返回操作数 4
Javascript
/**
* @param {number[]} nums
* @return {number}
*/
var minOperations = function(nums) {
const stack = []
let res = 0
for(const num of nums) {
while(stack.length && stack[stack.length - 1] > num) {
stack.pop()
}
// if the num is already 0, then do nothing
if(num === 0) {
continue
}
// if current number is larger than stack top, we must apply 1 extra op to make it 0
if(stack.length === 0 || stack[stack.length - 1] < num) {
res++
stack.push(num)
}
}
return res
};