Minimum Operations to Convert All Elements to Zero

medium monotonic stack greedy array

Problem

You are given an array nums of non-negative integers. In one operation you pick a subarray [i, j] and set every occurrence of the minimum non-negative value inside it to 0. Return the minimum number of operations needed to turn every element into 0.

The trick: think of the values by height. A run of equal positive values can be cleared together in one op, but a larger value sitting on top of a smaller one must be cleared in its own later op. Sweep left to right keeping a strictly increasing stack of the positive heights still "open"; each time a brand-new height opens, that's one operation.

Inputnums = [3,1,2,1]
Output3
Clear all the 1's together (1 op), then the lone 2 (1 op), then the 3 (1 op): 3 operations.

def minOperations(nums):
    stack = []          # strictly increasing positive heights still "open"
    ops = 0
    for v in nums:
        # close every open height taller than v: it is fully sealed off
        while stack and stack[-1] > v:
            stack.pop()
        if v > 0:
            # a height equal to the top is the same run -> no new op
            if not stack or stack[-1] < v:
                ops += 1            # a brand-new height opens here
                stack.append(v)
    return ops
function minOperations(nums) {
  const stack = [];          // strictly increasing open positive heights
  let ops = 0;
  for (const v of nums) {
    // close every open height taller than v
    while (stack.length && stack[stack.length - 1] > v) {
      stack.pop();
    }
    if (v > 0) {
      // equal to top -> same run, no new op
      if (!stack.length || stack[stack.length - 1] < v) {
        ops++;                 // a brand-new height opens
        stack.push(v);
      }
    }
  }
  return ops;
}
int minOperations(int[] nums) {
    Deque<Integer> stack = new ArrayDeque<>(); // increasing open heights
    int ops = 0;
    for (int v : nums) {
        // close every open height taller than v
        while (!stack.isEmpty() && stack.peek() > v) {
            stack.pop();
        }
        if (v > 0) {
            // equal to top -> same run, no new op
            if (stack.isEmpty() || stack.peek() < v) {
                ops++;             // a brand-new height opens
                stack.push(v);
            }
        }
    }
    return ops;
}
int minOperations(vector<int>& nums) {
    vector<int> stack;          // increasing open positive heights
    int ops = 0;
    for (int v : nums) {
        // close every open height taller than v
        while (!stack.empty() && stack.back() > v) {
            stack.pop_back();
        }
        if (v > 0) {
            // equal to top -> same run, no new op
            if (stack.empty() || stack.back() < v) {
                ops++;             // a brand-new height opens
                stack.push_back(v);
            }
        }
    }
    return ops;
}
Time: O(n) Space: O(n)