Open In App

Minimum length of X[] after removing at most K sub-arrays

Last Updated : 15 Nov, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array X[] of length N and an integer K. Then your task is to output minimum length of X[] after removing at most K number of sub-arrays, which satisfies the following conditions:

  • Size of the sub-array must be greater than 1.
  • First and last element of sub-array must be same.

Note: The sub-arrays which will satisfy the above condition will be non-intersecting. Formally, any sub-array which starts and ends with element A will not be overlapped with the any sub-array starting and ending with the element except A.

Examples: 

Input: N = 9, X[] = {2, 3, 1, 1, 9, 34, 56, 9, 9}, K = 3
Output: 2
Explanation: There are two sub-arrays {1, 1} and {9, 34, 56, 9, 9}, which start and end with same element having size greater than 1. Since we can remove at most K = 3 sub-arrays, but two of such kind are present. Therefore, after removing these two sub-arrays, the minimum length of the remained X[] will be = 2

Input: N = 4, X[] = {1, 2, 3, 4}, X = 2
Output: 4
Explanation: There are no sub-arrays such that it follows the given conditions. Therefore, we can’t remove any such sub-array. Hence the minimum length of X[] will be original as initial 4.

Approach: The problem can be solved by applying the Greedy approach.

We have to remove the K number of sub-arrays such that they follow the given conditions. As it is mentioned that sub-arrays must start and end with the same element. Thus we can get the first and last occurrence of an element from X[]. If the size of such sub-arrays is greater than 1 then store that length in a separate list. We can find the length of all such sub-arrays by iterating over X[] using a loop. After finding the length of all such sub-arrays, Sort them in any order(descending or ascending), and remove K number of subarrays of the biggest length from N, Formally, for minimizing the length of the remaining X[], we must remove the K sub-arrays having a maximum length. Now, the length of the remained X[] will be the minimum possible.

Below are the steps for the above approach:

  • Create an ArrayList say list and copy the element of X[] into it.
  • Create a HashMap say map for storing the length of sub-arrays.
  • Run a loop from i = 0 to i < list size,
    • Initialize a variable firstIndex = IndexOf(current_element)
    • Initialize a variable lastIndex = lastIndexOf(current_element)
    • Check if(firstIndex == lastIndex)
      • continue
    • else if the size is greater than 1, then put the length in Map 
      • map.put(current_element, lastIndex-firstIndex+1)
  • Create an ArrayList say length for storing frequencies from the map.
  • Sort the array length.
  • Iterate the length array from index i = size of length array to i ≥ 0 and k > 0 and subtract K biggest lengths from N,  
    N = N – lengths.get(i) and decrement the value of K by 1.
  • Print the value of N. 

Below is the code for the above approach:

C++




#include <bits/stdc++.h>
using namespace std;
 
// Method for printing minimum length
void remainedElements(int N, int K, vector<int>& X)
{
 
    // Map initialized for storing
    // lentgth of sub subarrays along
    // with the element
    unordered_map<int, int> map;
 
    // Loop for initilizing map with
    // length of such sub-arrays
    for (int i = 0; i < X.size(); i++) {
 
        // Getting first index of
        // current element
        int firstIndex = find(X.begin(), X.end(), X[i]) - X.begin();
 
        // Getting last index of
        // current element
        int lastIndex = find(X.rbegin(), X.rend(), X[i]) - X.rbegin();
 
        // Convert last index to
        // actual index in X
        lastIndex = X.size() - 1 - lastIndex;
 
        // If firstIndex is equal to
        // Last index Formally, there
        // is only one element of such
        // value Then ignore it, can't
        // be considered as sub-array
        // because size must be
        // greater than 1
        if (firstIndex == lastIndex) {
            continue;
        }
 
        // If size is greater than 1,
        // Then putting length in Map
        else {
            map[X[i]] = lastIndex - firstIndex + 1;
        }
    }
 
    // Vector for storing lengths
    // from map
    vector<int> lengths;
    for (auto it = map.begin(); it != map.end(); ++it) {
        lengths.push_back(it->second);
    }
 
    // Sorting sub-array's length
    sort(lengths.begin(), lengths.end());
 
    // Removing K number of such
    // sub-arrays with biggest size
    // formally, Iterating backward
    // in list of sorted lengths
    for (int i = lengths.size() - 1; i >= 0 && K > 0;
         i--) {
        N -= lengths[i];
        K--;
    }
 
    // Printing minimum length after
    // removing such K sub-arrays
    cout << N << endl;
}
 
// Driver Function
int main()
{
    // Inputs
    int N = 9;
    int K = 3;
    vector<int> X = { 12, 3, 1, 1, 2, 2, 2, 2, 5 };
 
    // Function call for printing
    // length after removing such
    // K number of sub-arrays
    remainedElements(N, K, X);
 
    return 0;
}


Java




// java code to implement the approach
 
import java.util.*;
public class GFG {
 
    // Driver Function
    public static void main(String[] args)
    {
 
        // Inputs
        int N = 9;
        int K = 3;
        int X[] = { 12, 3, 1, 1, 2, 2, 2, 2, 5 };
 
        // Function call for printing
        // length after removing such
        // K number of sub-arrays
        RemainedElements(N, K, X);
    }
 
    // Method for printing minimum length
    static void RemainedElements(int N, int K, int[] X)
    {
 
        // ArrayList for storing element
        // of X[] because it will be
        // convienient to find First and
        // last index of an element using
        // in-built func. such as
        // indexOf(), lastIndexOf()
        ArrayList<Integer> list = new ArrayList<>();
 
        // Loop for copying elements
        // from X[] to list
        for (int x : X)
            list.add(x);
 
        // Map initialized for storing
        // lentgth of sub subarrays along
        // with the element
        HashMap<Integer, Integer> map = new HashMap<>();
 
        // Loop for initilizing map with
        // length of such sub-arrays
        for (int i = 0; i < list.size(); i++) {
 
            // Getting first index of
            // current element
            int firstIndex = list.indexOf(list.get(i));
 
            // Getting last index of
            // current element
            int lastIndex = list.lastIndexOf(list.get(i));
 
            // If firstIndex is equal to
            // Last index Formally, there
            // is only one element of such
            // value Then ignore it, can't
            // be considered as sub-array
            // because size must be
            // greater than 1
            if (firstIndex == lastIndex) {
                continue;
            }
 
            // If size is greater than 1,
            // Then putting length in Map
            else {
                map.put(list.get(i),
                        lastIndex - firstIndex + 1);
            }
        }
 
        // List for storing lengths
        // from map
        ArrayList<Integer> lengths
            = new ArrayList<>(map.values());
 
        // Sorting sub-array's length
        lengths.sort(null);
 
        // Removing K number of such
        // sub-arrays with biggest size
        // formally, Iterating backward
        // in list of sorted lengths
        for (int i = lengths.size() - 1; i >= 0 && K > 0;
             i--) {
            N = N - lengths.get(i);
            K--;
        }
 
        // Printing minimum length after
        // removing such K sub-arrays
        System.out.println(N);
    }
}


Python3




import collections
 
#  Method for printing minimum length
def remainedElements(N, K, X):
   
   # Map initialized for storing
   # lentgth of sub subarrays along
   # with the element
    map = collections.defaultdict(int)
     
    # Loop for initilizing map with
    # length of such sub-arrays
    for i in range(len(X)):
       
      # Getting first index of
      # current element
        firstIndex = X.index(X[i])
         
        # Getting last index of
        # current element
        lastIndex = len(X) - 1 - X[::-1].index(X[i])
         
        # If firstIndex is equal to
        # Last index Formally, there
        # is only one element of such
        # value Then ignore it, can't
        # be considered as sub-array
        # because size must be
        # greater than 1
        if firstIndex == lastIndex:
            continue
        # If size is greater than 1,
        # Then putting length in Map
        else:
            map[X[i]] = lastIndex - firstIndex + 1
             
    # Vector for storing lengths
    # from map
    lengths = list(map.values())
     
    # sorting sub-array's length
    lengths.sort()
     
       # Removing K number of such
    # sub-arrays with biggest size
    # formally, Iterating backward
    # in list of sorted lengths
    for i in range(len(lengths) - 1, -1, -1):
        N -= lengths[i]
        K -= 1
        if K == 0:
            break
    # Printing minimum length after
    # removing such K sub-arrays
    print(N)
 
# Driver Function
N = 9
K = 3
X = [12, 3, 1, 1, 2, 2, 2, 2, 5]
remainedElements(N, K, X)


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
public class Program
{
    // Method for printing minimum length
    static void RemainedElements(int N, int K, List<int> X)
    {
        // Dictionary initialized for storing
        // length of sub subarrays along with the element
        Dictionary<int, int> map = new Dictionary<int, int>();
 
        // Loop for initializing map with
        // the length of such sub-arrays
        for (int i = 0; i < X.Count; i++)
        {
            // Getting first index of current element
            int firstIndex = X.IndexOf(X[i]);
 
            // Getting last index of current element
            int lastIndex = X.LastIndexOf(X[i]);
 
            // If firstIndex is equal to
            // last index, there is only one element of such value
            // Then ignore it, it can't be considered as sub-array
            // because size must be greater than 1
            if (firstIndex == lastIndex)
            {
                continue;
            }
            // If size is greater than 1,
            // then put length in the map
            else
            {
                map[X[i]] = lastIndex - firstIndex + 1;
            }
        }
 
        // List for storing lengths from map
        List<int> lengths = new List<int>();
        foreach (var kvp in map)
        {
            lengths.Add(kvp.Value);
        }
 
        // Sorting sub-array's length
        lengths.Sort();
 
        // Removing K number of such sub-arrays with the biggest size
        // Formally, iterating backward in the list of sorted lengths
        for (int i = lengths.Count - 1; i >= 0 && K > 0; i--)
        {
            N -= lengths[i];
            K--;
        }
 
        // Printing the minimum length after removing such K sub-arrays
        Console.WriteLine(N);
    }
 
    // Driver Function
    public static void Main()
    {
        // Inputs
        int N = 9;
        int K = 3;
        List<int> X = new List<int> { 12, 3, 1, 1, 2, 2, 2, 2, 5 };
 
        // Function call for printing
        // length after removing such
        // K number of sub-arrays
        RemainedElements(N, K, X);
    }
}


Javascript




function GFG(N, K, X) {
    // Map initialized for storing the length of sub-arrays along with
    // the element
    const map = new Map();
    // Loop for initializing the map with
    // the length of sub-arrays
    for (let i = 0; i < X.length; i++) {
        // Getting the first index of current element
        const firstIndex = X.indexOf(X[i]);
        // Getting the last index of current element
        const lastIndex = X.lastIndexOf(X[i]);
        // If firstIndex is equal to the last index
        // ignore it (size must be greater than 1)
        if (firstIndex === lastIndex) {
            continue;
        } else {
            // Calculate the length and store it in the map
            map.set(X[i], lastIndex - firstIndex + 1);
        }
    }
    // Get an array of sub-array lengths from the map
    const lengths = Array.from(map.values());
    // Sort the sub-array lengths
    lengths.sort((a, b) => a - b);
    // Removing K number of sub-arrays with biggest size
    for (let i = lengths.length - 1; i >= 0 && K > 0; i--) {
        N -= lengths[i];
        K--;
    }
    // Printing the minimum length after removing K sub-arrays
    console.log(N);
}
// Driver Function
function main() {
    // Inputs
    const N = 9;
    const K = 3;
    const X = [12, 3, 1, 1, 2, 2, 2, 2, 5];
    // Function call for calculating the minimum length after
    //  removing K sub-arrays
    GFG(N, K, X);
}
main();


Output

3




Time Complexity: O(N * LogN)
Space Complexity: O(N)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads