Make Array Non-decreasing

medium array greedy monotonic stack

Problem

You are given an integer array nums. In one operation you may pick a non-empty subarray and replace the whole subarray with a single element equal to its maximum. Return the maximum possible size of the array after zero or more operations such that the result is non-decreasing.

Because replacing a subarray with its max can only raise the value at that position, an element survives only if some kept element to its right is at least as large. So we scan from the right, keep an element whenever it is ≤ the running ceiling, and absorb it otherwise.

Inputnums = [4, 2, 5, 3, 5]
Output3
Merge [2,5]→5 then [3,5]→5 to get [4,5,5], a non-decreasing array of size 3.

def maximumPossibleSize(nums):
    cur = float('inf')          # ceiling allowed at the current right boundary
    keep = 0                    # how many original elements survive
    for i in range(len(nums) - 1, -1, -1):
        if nums[i] <= cur:
            keep += 1           # this element fits under the ceiling, keep it
            cur = nums[i]       # it becomes the new (lower) ceiling on its left
        # else: nums[i] > cur, absorb it into the subarray on its right
    return keep
function maximumPossibleSize(nums) {
  let cur = Infinity;           // ceiling allowed at the current right boundary
  let keep = 0;                 // how many original elements survive
  for (let i = nums.length - 1; i >= 0; i--) {
    if (nums[i] <= cur) {
      keep++;                   // this element fits under the ceiling, keep it
      cur = nums[i];            // it becomes the new (lower) ceiling on its left
    }
    // else: nums[i] > cur, absorb it into the subarray on its right
  }
  return keep;
}
int maximumPossibleSize(int[] nums) {
    long cur = Long.MAX_VALUE;  // ceiling allowed at the current right boundary
    int keep = 0;               // how many original elements survive
    for (int i = nums.length - 1; i >= 0; i--) {
        if (nums[i] <= cur) {
            keep++;             // this element fits under the ceiling, keep it
            cur = nums[i];      // it becomes the new (lower) ceiling on its left
        }
        // else: nums[i] > cur, absorb it into the subarray on its right
    }
    return keep;
}
int maximumPossibleSize(vector<int>& nums) {
    long long cur = LLONG_MAX;  // ceiling allowed at the current right boundary
    int keep = 0;               // how many original elements survive
    for (int i = (int)nums.size() - 1; i >= 0; i--) {
        if (nums[i] <= cur) {
            keep++;             // this element fits under the ceiling, keep it
            cur = nums[i];      // it becomes the new (lower) ceiling on its left
        }
        // else: nums[i] > cur, absorb it into the subarray on its right
    }
    return keep;
}
Time: O(n) Space: O(1)