Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Program to find shortest subarray to be removed to make array sorted in Python
Given an array, we need to find the shortest subarray to remove so that the remaining elements are in non-decreasing (sorted) order. This problem involves finding the longest possible sorted subsequence that can be formed by keeping elements from both ends of the array.
So, if the input is like arr = [10,20,30,100,40,20,30,50], then the output will be 3 because we can remove [100, 40, 20] which is the smallest subarray of length 3, and by removing these all remaining elements are in non-decreasing order [10,20,30,30,50].
Algorithm
To solve this, we will follow these steps:
- Add sentinel values: 0 at the beginning and infinity at the end
- Use two pointers to build sorted sequences from left and right ends
- Find the maximum length of combined sorted sequences
- Return original length minus maximum sorted length
Example
def solve(arr):
n = len(arr)
# Add sentinel values to handle edge cases
arr = [0] + arr + [float("inf")]
A, B = [], [] # A: left sorted, B: right sorted
p, q = 1, len(arr) - 2 # Pointers for left and right
M = 0 # Maximum length of sorted subsequence
while p <= q:
if arr[p-1] <= arr[p]:
# Extend left sorted sequence
A.append(arr[p])
p += 1
elif arr[q] <= arr[q+1]:
# Extend right sorted sequence
B.append(arr[q])
# Remove elements from A that break sorting with B
while A and A[-1] > B[-1]:
A.pop()
q -= 1
else:
# Can't extend either sequence
break
# Update maximum sorted length
M = max(M, len(A) + len(B))
return n - M
# Test the function
arr = [10, 20, 30, 100, 40, 20, 30, 50]
result = solve(arr)
print(f"Shortest subarray length to remove: {result}")
print(f"Original array: {arr}")
Shortest subarray length to remove: 3 Original array: [10, 20, 30, 100, 40, 20, 30, 50]
How It Works
The algorithm uses a two-pointer approach:
- Left pointer (p): Builds the longest increasing sequence from the left
- Right pointer (q): Builds the longest increasing sequence from the right
- Compatibility check: Ensures elements from left sequence ? elements from right sequence
- Result: Total length minus maximum sorted subsequence length
Step-by-Step Trace
For array [10,20,30,100,40,20,30,50]:
def solve_with_trace(arr):
n = len(arr)
arr = [0] + arr + [float("inf")]
A, B = [], []
p, q = 1, len(arr) - 2
M = 0
print(f"Modified array: {arr}")
print(f"Initial: p={p}, q={q}")
step = 1
while p <= q:
print(f"\nStep {step}:")
if arr[p-1] <= arr[p]:
A.append(arr[p])
print(f" Extended left: A={A}")
p += 1
elif arr[q] <= arr[q+1]:
B.append(arr[q])
print(f" Extended right: B={B}")
while A and A[-1] > B[-1]:
removed = A.pop()
print(f" Removed {removed} from A: A={A}")
q -= 1
else:
print(" Cannot extend either sequence, breaking")
break
M = max(M, len(A) + len(B))
print(f" A={A}, B={B}, M={M}")
step += 1
return n - M
# Trace the execution
arr = [10, 20, 30, 100, 40, 20, 30, 50]
result = solve_with_trace(arr)
print(f"\nFinal result: {result}")
Modified array: [0, 10, 20, 30, 100, 40, 20, 30, 50, inf] Initial: p=1, q=8 Step 1: Extended left: A=[10] A=[10], B=[], M=1 Step 2: Extended left: A=[10, 20] A=[10, 20], B=[], M=2 Step 3: Extended left: A=[10, 20, 30] A=[10, 20, 30], B=[], M=3 Step 4: Extended left: A=[10, 20, 30, 100] A=[10, 20, 30, 100], B=[], M=4 Step 5: Extended right: B=[50] Removed 100 from A: A=[10, 20, 30] A=[10, 20, 30], B=[50], M=4 Step 6: Extended right: B=[50, 30] A=[10, 20, 30], B=[50, 30], M=5 Final result: 3
Conclusion
This algorithm efficiently finds the shortest subarray to remove by building sorted sequences from both ends and ensuring compatibility between them. The time complexity is O(n) and space complexity is O(n) for the auxiliary arrays.
