Minimum Number of Removals to Make Mountain Array

hard dp lis

Problem

You are given an integer array nums. A mountain array has at least 3 elements and climbs strictly up to a single peak, then falls strictly down — the peak cannot be the first or last element, and equal neighbours are not allowed on either slope. Return the minimum number of elements to delete so that the remaining array is a mountain (the input is guaranteed to allow one).

Constraints: 3 ≤ nums.length ≤ 1000 and 1 ≤ nums[i] ≤ 10⁹; deletions keep the relative order of the surviving elements, so we are really choosing a subsequence to keep.

Inputnums = [2,1,1,5,6,2,3,1]
Output3
Removing the elements at indices 0, 1 and 5 leaves [1,5,6,3,1], which rises strictly to 6 and then falls strictly.

def minimum_mountain_removals(nums):
    n = len(nums)
    lis = [1] * n
    for i in range(n):
        for j in range(i):
            if nums[j] < nums[i]:
                lis[i] = max(lis[i], lis[j] + 1)
    lds = [1] * n
    for i in range(n - 1, -1, -1):
        for j in range(i + 1, n):
            if nums[j] < nums[i]:
                lds[i] = max(lds[i], lds[j] + 1)
    best = 0
    for i in range(n):
        if lis[i] >= 2 and lds[i] >= 2:
            best = max(best, lis[i] + lds[i] - 1)
    return n - best
function minimumMountainRemovals(nums) {
  const n = nums.length;
  const lis = new Array(n).fill(1);
  for (let i = 0; i < n; i++)
    for (let j = 0; j < i; j++)
      if (nums[j] < nums[i]) lis[i] = Math.max(lis[i], lis[j] + 1);
  const lds = new Array(n).fill(1);
  for (let i = n - 1; i >= 0; i--)
    for (let j = i + 1; j < n; j++)
      if (nums[j] < nums[i]) lds[i] = Math.max(lds[i], lds[j] + 1);
  let best = 0;
  for (let i = 0; i < n; i++)
    if (lis[i] >= 2 && lds[i] >= 2)
      best = Math.max(best, lis[i] + lds[i] - 1);
  return n - best;
}
int minimumMountainRemovals(int[] nums) {
    int n = nums.length;
    int[] lis = new int[n], lds = new int[n];
    Arrays.fill(lis, 1);
    Arrays.fill(lds, 1);
    for (int i = 0; i < n; i++)
        for (int j = 0; j < i; j++)
            if (nums[j] < nums[i]) lis[i] = Math.max(lis[i], lis[j] + 1);
    for (int i = n - 1; i >= 0; i--)
        for (int j = i + 1; j < n; j++)
            if (nums[j] < nums[i]) lds[i] = Math.max(lds[i], lds[j] + 1);
    int best = 0;
    for (int i = 0; i < n; i++)
        if (lis[i] >= 2 && lds[i] >= 2)
            best = Math.max(best, lis[i] + lds[i] - 1);
    return n - best;
}
int minimumMountainRemovals(vector<int>& nums) {
    int n = nums.size();
    vector<int> lis(n, 1), lds(n, 1);
    for (int i = 0; i < n; i++)
        for (int j = 0; j < i; j++)
            if (nums[j] < nums[i]) lis[i] = max(lis[i], lis[j] + 1);
    for (int i = n - 1; i >= 0; i--)
        for (int j = i + 1; j < n; j++)
            if (nums[j] < nums[i]) lds[i] = max(lds[i], lds[j] + 1);
    int best = 0;
    for (int i = 0; i < n; i++)
        if (lis[i] >= 2 && lds[i] >= 2)
            best = max(best, lis[i] + lds[i] - 1);
    return n - best;
}
Time: O(n²) Space: O(n)