Problem: Shortest Subarray to be Removed to Make Array Sorted

Given an integer array `arr`, remove a subarray (can be empty) from `arr` such
that the remaining elements in `arr` are non-decreasing.

Return the length of the shortest subarray to remove.

A subarray is a contiguous subsequence of the array.


Python solution:
import math
import itertools
import bisect
import collections
import string
import heapq
import functools
import sortedcontainers
from typing import List, Dict, Tuple, Iterator

class Solution:
  def findLengthOfShortestSubarray(self, arr: List[int]) -> int:
    n = len(arr)
    l = 0
    r = n - 1

    while l < n - 1 and arr[l + 1] >= arr[l]:
      l += 1
    while r > 0 and arr[r - 1] <= arr[r]:
      r -= 1
    ans = min(n - 1 - l, r)

    i = l
    j = n - 1
    while i >= 0 and j >= r and j > i:
      if arr[i] <= arr[j]:
        j -= 1
      else:
        i -= 1
      ans = min(ans, j - i)

    return ans


Java solution:
class Solution {
  public int findLengthOfShortestSubarray(int[] arr) {
    final int n = arr.length;
    int l = 0;
    int r = n - 1;

    // arr[0..l] is non-decreasing prefix.
    while (l < n - 1 && arr[l + 1] >= arr[l])
      ++l;
    // arr[r..n - 1] is non-decreasing suffix.
    while (r > 0 && arr[r - 1] <= arr[r])
      --r;
    // Remove arr[l + 1..n - 1] or arr[0..r - 1]
    int ans = Math.min(n - 1 - l, r);

    // Since arr[0..l] and arr[r..n - 1] are non-decreasing, we place pointers
    // at the rightmost indices, l and n - 1, and greedily shrink them toward
    // the leftmost indices, 0 and r, respectively. By removing arr[i + 1..j],
    // we ensure that `arr` becomes non-decreasing.
    int i = l;
    int j = n - 1;
    while (i >= 0 && j >= r && j > i) {
      if (arr[i] <= arr[j])
        --j;
      else
        --i;
      ans = Math.min(ans, j - i);
    }

    return ans;
  }
}


C++ solution:
class Solution {
 public:
  int findLengthOfShortestSubarray(vector<int>& arr) {
    const int n = arr.size();
    int l = 0;
    int r = n - 1;

    // arr[0..l] is non-decreasing.
    while (l < n - 1 && arr[l + 1] >= arr[l])
      ++l;
    // arr[r..n - 1] is non-decreasing.
    while (r > 0 && arr[r - 1] <= arr[r])
      --r;
    // Remove arr[l + 1..n - 1] or arr[0..r - 1].
    int ans = min(n - 1 - l, r);

    // Since arr[0..l] and arr[r..n - 1] are non-decreasing, we place pointers
    // at the rightmost indices, l and n - 1, and greedily shrink them toward
    // the leftmost indices, 0 and r, respectively. By removing arr[i + 1..j],
    // we ensure that `arr` becomes non-decreasing.
    int i = l;
    int j = n - 1;
    while (i >= 0 && j >= r && j > i) {
      if (arr[i] <= arr[j])
        --j;
      else
        --i;
      ans = min(ans, j - i);
    }

    return ans;
  }
};