Open In App

Find Minimum Removals for Valid Block Sequences

Last Updated : 16 Feb, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] of size n, a sequence is called valid if it is in series of blocks where each starting element denotes the length of the block i.e first comes the length of the block then its element, for example the sequence [3 3 4 5 2 6 1], here the blocks are [3 3 4 5] and [2 6 1]. In one operation you can remove any one element of the array. The task is to determine the minimum number of operations required to make the array a valid sequence.

Example:

Input: arr = [3 4 1 6 7 7]
Output: 1
Explanation: remove 3 then the array becomes [4 1 6 7 7]

Input: arr = {4, 5, 5, 1, 5}
Output: 0

Approach:

The intuition behind the solution is to use dynamic programming to keep track of the minimum number of operations required to make the segment from i to n valid. Here, n is the size of the array, and i ranges from 1 to n (1-based indexing is considered here)

The dynamic programming approach involves creating an array dp[], where dp[i] represents the minimum number of operations required to make the segment from i to n valid.

There are two possible ways to make the segment from i to n valid:

  1. Remove the element at position i: If we remove the element at position i, then we need to make the segment from i+1 to n valid. The number of operations required for this is dp[i+1]+1, because we perform one operation (removal) plus whatever operations are needed to make the rest of the array valid.
  2. Skip to the end of the block starting at i: If the element at position i denotes the length of a block, we can skip to the end of this block and make the segment from i+a[i]+1 to n valid. The number of operations required for this is dp[i+a[i]+1], because we don’t perform any removals, but we need to make the rest of the array valid. Note that we need to handle the case where i+a[i]+1 is greater than n separately.

By considering these two possibilities for each position i in the array, we can fill up the dp[] array and find the minimum number of operations required to make the entire array a valid sequence. The final answer will be dp[1] (1-based indexing is considered here) , which represents the minimum number of operations required to make the segment from 1 to n valid.

Steps-by-step approach:

  • Initialize the dynamic programming arr with large values
  • Helper function to safely access the dp array
  • Base case: the last element can always be made valid by removing it by dp[n – 1] = 1
  • Fill the dp array from right to left
    • Either remove the current element or skip to the end of the block by dp[i] = min(dp[i + 1] + 1, getDP(i + arr[i] + 1))
  • The minimum number of operations to make the whole arr valid is dp[0]

Below is the implementation of the above approach:

C++




#include <bits/stdc++.h>
#include <vector>
 
using namespace std;
 
// Function to solve the problem for a single test case
void solve(int& n, vector<int>& arr)
{
 
    // Initialize the dynamic programming arr with large
    // values
    vector<int> dp(n + 1, n + 1);
 
    // Helper function to safely access the dp array
    auto getDP = [&](int pos) {
        if (pos > n) {
            return n + 1;
        }
        if (pos == n) {
            return 0;
        }
        return dp[pos];
    };
 
    // Base case: the last element can always be made valid
    // by removing it
    dp[n - 1] = 1;
 
    // Fill the dp arr from right to left
    for (int i = n - 2; i >= 0; --i) {
        // Either remove the current element or skip to the
        // end of the block
        dp[i] = min(dp[i + 1] + 1, getDP(i + arr[i] + 1));
    }
 
    // The minimum number of operations to make the whole
    // array valid is dp[0]
    cout << dp[0] << endl;
}
 
int main()
{
    // number of elements in the arr
    int n = 4;
 
    vector<int> arr = { 5, 6, 3, 2 };
    solve(n, arr);
 
    return 0;
}


Java




import java.util.Arrays;
 
public class Main {
 
    // Function to solve the problem for a single test case
    private static void solve(int n, int[] arr)
    {
 
        // Initialize the dynamic programming array with
        // large values
        int[] dp = new int[n + 1];
        Arrays.fill(dp, n + 1);
 
        // Helper function to safely access the dp array
        // Base case: the last element can always be made
        // valid by removing it
        dp[n - 1] = 1;
 
        // Fill the dp array from right to left
        for (int i = n - 2; i >= 0; --i) {
            // Either remove the current element or skip to
            // the end of the block
            dp[i] = Math.min(dp[i + 1] + 1,
                             (i + arr[i] + 1 <= n)
                                 ? dp[i + arr[i] + 1]
                                 : n + 1);
        }
 
        // The minimum number of operations to make the
        // whole array valid is dp[0]
        System.out.println(dp[0]);
    }
 
    public static void main(String[] args)
    {
        // Number of elements in the array
        int n = 4;
 
        int[] arr = { 5, 6, 3, 2 };
        solve(n, arr);
    }
}


Python3




# Python program for the above approach
# Function to solve the problem for a single test case
def solve(n, arr):
    # Initialize the dynamic programming array with large values
    dp = [n + 1] * (n + 1)
 
    # Base case: the last element can always be made valid by removing it
    dp[n - 1] = 1
 
    # Helper function to safely access the dp array
    def getDP(pos):
        if pos > n:
            return n + 1
        if pos == n:
            return 0
        return dp[pos]
 
    # Fill the dp array from right to left
    for i in range(n - 2, -1, -1):
        # Either remove the current element or skip to the end of the block
        dp[i] = min(dp[i + 1] + 1, getDP(i + arr[i] + 1))
 
    # The minimum number of operations to make the whole array valid is dp[0]
    print(dp[0])
 
# Main function
if __name__ == "__main__":
    # Number of elements in the array
    n = 4
 
    arr = [5, 6, 3, 2]
    solve(n, arr)
 
# This code is contributed by Susobhan Akhuli


C#




using System;
using System.Collections.Generic;
 
class Program
{
    // Function to solve the problem for a single test case
    static void Solve(ref int n, List<int> arr)
    {
        // Initialize the dynamic programming array with large values
        List<int> dp = new List<int>(new int[n + 1]);
 
        // Create a local variable to store the value of 'n'
        int localN = n;
 
        // Helper function to safely access the dp array
        Func<int, int> getDP = (int pos) =>
        {
            if (pos > localN)
                return localN + 1;
            if (pos == localN)
                return 0;
            return dp[pos];
        };
 
        // Base case: the last element can always be made valid by removing it
        dp[localN - 1] = 1;
 
        // Fill the dp array from right to left
        for (int i = localN - 2; i >= 0; --i)
        {
            // Either remove the current element or skip to the end of the block
            dp[i] = Math.Min(dp[i + 1] + 1, getDP(i + arr[i] + 1));
        }
 
        // The minimum number of operations to make the whole array valid is dp[0]
        Console.WriteLine(dp[0]);
    }
 
    static void Main()
    {
        // Number of elements in the array
        int n = 4;
 
        List<int> arr = new List<int> { 5, 6, 3, 2 };
        Solve(ref n, arr);
    }
}


Javascript




// Javascript program for the above approach
// Function to solve the problem for a single test case
function solve(n, arr) {
    // Initialize the dynamic programming array with large values
    let dp = new Array(n + 1).fill(n + 1);
 
    // Base case: the last element can always be made valid by removing it
    dp[n - 1] = 1;
 
    // Fill the dp array from right to left
    for (let i = n - 2; i >= 0; --i) {
        // Either remove the current element or skip to the end of the block
        dp[i] = Math.min(dp[i + 1] + 1, (i + arr[i] + 1 <= n) ? dp[i + arr[i] + 1] : n + 1);
    }
 
    // The minimum number of operations to make the whole array valid is dp[0]
    console.log(dp[0]);
}
 
// Number of elements in the array
let n = 4;
 
// Array of elements
let arr = [5, 6, 3, 2];
 
// Solve the problem for the given test case
solve(n, arr);
 
// This code is contributed by Susobhan Akhuli


Output

4


Time Complexity: O(n), where n is the size of the array.
Auxiliary Space: O(n)



    Like Article
    Suggest improvement
    Share your thoughts in the comments

    Similar Reads