Open In App

Find the minimum value of K required to remove all elements from the array in at most M operations

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

Given array A[] of size N and integer M, Perform the following operation until the array becomes empty. Choose K and the pick first K elements of array A[]. In one operation subtract all these chosen K elements by 1 if any element becomes zero that element will be deleted and it will be replaced by K + 1’th element of the array. The task for this problem is to find the minimum value of K to remove all elements of an array in at most M operations.

Examples:

Input: A[] = {4, 7, 8, 6, 4}, M = 8
Output: 4
Explanation: Chose K = 4 initially we have first four elements of array S = [4, 7, 8, 6]

  • In the first operation subtract 1 from chosen set S, and it becomes [3, 6, 7, 5]
  • In the second operation subtract 1 from the chosen set S, and it becomes [2, 5, 6, 4]
  • In the third operation subtract 1 from chosen set S, and it becomes [1, 4, 5, 3]
  • In the fourth operation subtract 1 from the chosen set S, and it becomes [0, 3, 4, 2] since one of the elements becomes zero it will be replaced by the next element which is 4 new S is [3, 4, 2, 4].
  • In the fifth operation subtract 1 from chosen set S, and it becomes [2, 3, 1, 3]
  • In the Sixth operation subtract 1 from chosen set S, and it becomes [1, 2, 0, 2] since one of the elements becomes zero since there is no other element left it will be removed new S becomes [1, 2, 2]
  • In the seventh operation subtract 1 from the chosen set S, and it becomes [0, 1, 1] since one of the elements becomes zero since there is no other element left it will be removed new S becomes [1, 1]
  • In the eighth operation subtract 1 from the chosen set S, and it becomes [0, 0] since all element becomes zero remove them all.

In 8 operations all elements of the array are deleted which is less than equal to the number of allowed operations.

Input: A[] = {3, 5, 2, 8, 7, 4}, M = 11
Output: 3
Explanation: Chose K= 3 initially we have the first three elements of array S = [3, 5, 2]

  • In the first operation subtract 1 from the chosen set S, and it becomes [2, 4, 1]
  • In the second operation subtract 1 from the chosen set S, and it becomes [1, 3, 0] Since onthat element with the next element of the array S becomes [1, 3, 8]
  • In the third operation subtract 1 from the chosen set S, and it becomes [0, 2, 7] Since one of the elements becomes zero replace that element with the next element of the array S becomes [2, 7, 7]
  • In fourth operation subtract 1 from chosen set S, it becomes [1, 6, 6]
  • In fifth operation subtract 1 from chosen set S, it becomes [0, 5, 5] since one of the elements becomes zero replace that element with next element of array S becomes [5, 5, 4]
  • In sixth operation subtract 1 from chosen set S, it becomes [4, 4, 3]
  • In seventh operation subtract 1 from chosen set S, it becomes [3, 3, 2]
  • In eighth operation subtract 1 from chosen set S, it becomes [2, 2, 1]
  • In ninth operation subtract 1 from chosen set S, it becomes [1, 1, 0] since one of the elements becomes zero since there is no other element left it will be simply removed new S becomes [1, 1]
  • In tenth operation subtract 1 from chosen set S, it becomes [0, 0] since all elements becomes zero remove them all.

In 10 operations all elements of array are deleted which are less than equal to number of allowed operations.

Minimum value of K to remove all elements from array in at most M operations Using Binary Search:

Binary Search can be used to solve this problem and the range of binary search will be 1 to M. f(K) is monotonic function that represents whether all elements from array can be removed in at most M operations with by selecting K. it is of the form FFFFFFFTTTTTTT. we have to find when the first time function becomes true using Binary Search.

We will use multiset to check if all the elements can be removed in at most M operations. we will maintain variable currentOperations and maxOperations .

A[] = {4, 7, 8, 6, 4}, N = 5

since we cannot just take first K = 4 elements and perform operations of subtraction one by one we will do the following.

For K = 4 we will have multiset MS[] = {4, 6, 7, 8} initially, smallest number will be number of operations we need to perform to make the smallest element zero as told delete that element and insert next element. But rather than subtracting each element of multiset by 4 we will maintain another variable currentOperations which will make sure the relative ordering of incoming elements. After deleting 4 increase the currentOperations by 4 and incoming element is A[5] = 4 will be added with currentOperations = 4 then inserted in multiset MS[] becomes {6, 7, 8, 8}. each element of multiset is actually a Acutal[] = MS[] – {currentOperations} = {6 – 4, 7 – 4, 8 – 4, 8 – 4} = {2, 3, 4, 4}

In 4 operations whole multiset can be made empty. currentOperations = 4 increased by 4

So for K = 4 in 8 operations whole array A[] can be made empty by performing operations given in above problem.

Below are the steps for the above approach:

  • Set low and high range of binary search.
  • ispos(K) function is used to check whether elements from array can be removed in at most M operations with K.
  • Run while loop till high and low are not equal.
  • In while loop find middle element and store it in mid variable.
  • Check if that K = mid is enough to remove all elements from array in at most M operations using ispos() function. If it is true then set high = mid else low = mid + 1.
  • After loop ends if ispos() true for low then return low else check if it is true for high then return high else return -1.

Below is the implementation of the above approach:

C++




// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to check given K is enough to
// empty the array in at most M operations
bool ispos(int K, int A[], int N, int M)
{
    // variable for tracking the
    int currentNumberOfOperations = 0;
 
    // variable for tracking maxium number of operations
    int maximumNumberOfOperations = 0;
 
    // Declaring multiset for K elements
    multiset<int> ms;
 
    // inserting first K elements in multiset
    for (int i = 0; i < K; i++)
        ms.insert(A[i]);
 
    // delete smallest element and add new element
    for (int i = K; i < N; i++) {
 
        // smallest element of multiset
        int first = *ms.begin() - currentNumberOfOperations;
 
        // delete smallest element from multiset
        ms.erase(ms.begin());
 
        // the number of operations already performed
        currentNumberOfOperations += first;
 
        // insert new element with offset number of
        // operations
        ms.insert(A[i] + currentNumberOfOperations);
 
        // update maximum number of operations
        maximumNumberOfOperations
            = max(maximumNumberOfOperations, *(--ms.end()));
    }
 
    // if required number of operations are at most
    // M return 1 else 0
    return maximumNumberOfOperations <= M;
}
 
// Function to Minimum value of K to remove
// all elements from array in at most M operations
int findMinM(int A[], int N, int M)
{
 
    // Range of binary search
    int low = 1, high = M;
 
    // Running loop till high
    // is not equal to low
    while (high - low > 1) {
 
        // mid is average of low and high
        int mid = (low + high) / 2;
 
        // Checking test function
        if (ispos(mid, A, N, M)) {
            high = mid;
        }
        else {
            low = mid + 1;
        }
    }
 
    // Checking whether low can be answer
    if (ispos(low, A, N, M))
        return low;
 
    // If not then it is high
    else if (ispos(high, A, N, M))
        return high;
    // if not possible
    return -1;
}
 
// Driver Code
int32_t main()
{
 
    // Input 1
    int N = 5, M = 8;
    int A[] = { 4, 7, 8, 6, 4 };
 
    // Function Call
    cout << findMinM(A, N, M) << endl;
 
    return 0;
}


Java




// Java program for the above approach
import java.util.Arrays;
import java.util.TreeSet;
 
class GFG {
    // Function to check if given K is enough to
    // empty the array in at most M operations
    static boolean isPos(int K, int[] A, int N, int M)
    {
        int currentNumberOfOperations = 0;
        int maximumNumberOfOperations = 0;
 
        // Declaring TreeSet for K elements
        TreeSet<Integer> treeSet = new TreeSet<>();
 
        // Inserting first K elements in TreeSet
        for (int i = 0; i < K; i++)
            treeSet.add(A[i]);
 
        // Delete smallest element and add new element
        for (int i = K; i < N; i++) {
            // Smallest element of TreeSet
            int first = treeSet.first()
                        - currentNumberOfOperations;
 
            // Delete smallest element from TreeSet
            treeSet.remove(treeSet.first());
 
            // The number of operations already performed
            currentNumberOfOperations += first;
 
            // Insert new element with offset number of
            // operations
            treeSet.add(A[i] + currentNumberOfOperations);
 
            // Update maximum number of operations
            maximumNumberOfOperations = Math.max(
                maximumNumberOfOperations, treeSet.last());
        }
 
        // If required number of operations are at most M,
        // return true; otherwise, false
        return maximumNumberOfOperations <= M;
    }
 
    // Function to find the minimum value of K to remove
    // all elements from the array in at most M operations
    static int findMinM(int[] A, int N, int M)
    {
        // Range of binary search
        int low = 1, high = M;
 
        // Running loop till high is not equal to low
        while (high - low > 1) {
            // Mid is the average of low and high
            int mid = (low + high) / 2;
 
            // Checking the test function
            if (isPos(mid, A, N, M)) {
                high = mid;
            }
            else {
                low = mid + 1;
            }
        }
 
        // Checking whether low can be the answer
        if (isPos(low, A, N, M))
            return low;
 
        // If not, then it is high
        else if (isPos(high, A, N, M))
            return high;
 
        // If not possible
        return -1;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        // Input 1
        int N = 5, M = 8;
        int[] A = { 4, 7, 8, 6, 4 };
 
        // Function Call
        System.out.println(findMinM(A, N, M));
    }
}
 
// This code is contributed by Susobhan Akhuli


Python3




from sortedcontainers import SortedList
 
# Function to check if given K is enough to
# empty the array in at most M operations
 
 
def is_pos(K, A, N, M):
    current_number_of_operations = 0
    maximum_number_of_operations = 0
 
    # Declaring SortedList for K elements
    sl = SortedList()
 
    # Inserting first K elements in SortedList
    for i in range(K):
        sl.add(A[i])
 
    # Delete smallest element and add new element
    for i in range(K, N):
        # Smallest element of SortedList
        first = sl[0] - current_number_of_operations
 
        # Delete smallest element from SortedList
        sl.discard(sl[0])
 
        # The number of operations already performed
        current_number_of_operations += first
 
        # Insert new element with offset number of operations
        sl.add(A[i] + current_number_of_operations)
 
        # Update maximum number of operations
        maximum_number_of_operations = max(
            maximum_number_of_operations, sl[-1])
 
    # If required number of operations are at most M, return True, else False
    return maximum_number_of_operations <= M
 
# Function to find the minimum value of K to remove
# all elements from the array in at most M operations
 
 
def find_min_M(A, N, M):
    # Range of binary search
    low, high = 1, M
 
    # Running loop until high is not equal to low
    while high - low > 1:
        # Mid is the average of low and high
        mid = (low + high) // 2
 
        # Checking test function
        if is_pos(mid, A, N, M):
            high = mid
        else:
            low = mid + 1
 
    # Checking whether low can be the answer
    if is_pos(low, A, N, M):
        return low
 
    # If not, then it is high
    elif is_pos(high, A, N, M):
        return high
 
    # If not possible
    return -1
 
 
# Driver Code
if __name__ == "__main__":
    # Input 1
    N, M = 5, 8
    A = [4, 7, 8, 6, 4]
 
    # Function Call
    print(find_min_M(A, N, M))


C#




using System;
using System.Collections.Generic;
 
class Program
{
    // Function to check if given K is enough to empty the array in at most M operations
    static bool IsPos(int K, int[] A, int N, int M)
    {
        int currentNumberOfOperations = 0;
        int maximumNumberOfOperations = 0;
        var ms = new SortedSet<int>();
 
        for (int i = 0; i < K; i++)
            ms.Add(A[i]);
 
        for (int i = K; i < N; i++)
        {
            int first = ms.Min - currentNumberOfOperations;
            ms.Remove(ms.Min);
            currentNumberOfOperations += first;
            ms.Add(A[i] + currentNumberOfOperations);
            maximumNumberOfOperations = Math.Max(maximumNumberOfOperations, ms.Max);
        }
 
        return maximumNumberOfOperations <= M;
    }
 
    // Function to find minimum value of K to remove all elements from the array in at most M operations
    static int FindMinM(int[] A, int N, int M)
    {
        int low = 1, high = M;
 
        while (high - low > 1)
        {
            int mid = (low + high) / 2;
 
            if (IsPos(mid, A, N, M))
            {
                high = mid;
            }
            else
            {
                low = mid + 1;
            }
        }
 
        if (IsPos(low, A, N, M))
            return low;
        else if (IsPos(high, A, N, M))
            return high;
 
        return -1;
    }
 
    static void Main()
    {
        int N = 5, M = 8;
        int[] A = { 4, 7, 8, 6, 4 };
 
        Console.WriteLine(FindMinM(A, N, M));
    }
}


Javascript




// Javascript program for the above approach
 
// Function to check if given K is enough to
// empty the array in at most M operations
function ispos(K, A, N, M) {
    let currentNumberOfOperations = 0;
    let maximumNumberOfOperations = 0;
    let ms = new Set();
 
    // Insert first K elements in set
    for (let i = 0; i < K; i++)
        ms.add(A[i]);
 
    // Delete smallest element and add new element
    for (let i = K; i < N; i++) {
        let first = Math.min(...ms) - currentNumberOfOperations;
        ms.delete(Math.min(...ms));
 
        currentNumberOfOperations += first;
        ms.add(A[i] + currentNumberOfOperations);
        maximumNumberOfOperations = Math.max(maximumNumberOfOperations, Math.max(...ms));
    }
 
    // Return 1 if required number of operations are at most M, else 0
    return maximumNumberOfOperations <= M;
}
 
// Function to find minimum value of K to remove
// all elements from array in at most M operations
function findMinM(A, N, M) {
    let low = 1, high = M;
 
    // Running loop till high is not equal to low
    while (high - low > 1) {
        let mid = Math.floor((low + high) / 2);
 
        // Checking test function
        if (ispos(mid, A, N, M)) {
            high = mid;
        } else {
            low = mid + 1;
        }
    }
 
    // Checking whether low can be answer
    if (ispos(low, A, N, M))
        return low;
    // If not, then it is high
    else if (ispos(high, A, N, M))
        return high;
    // If not possible
    return -1;
}
 
// Driver Code
let N = 5, M = 8;
let A = [4, 7, 8, 6, 4];
 
// Function Call
console.log(findMinM(A, N, M));
 
// This code is contributed by Susobhan Akhuli


Output

4

Complexity Analysis:

Time Complexity: O(N * logN * log(R – L)), NlogN time complexity of ispos() function and other log(R – L) is number of checks made by binary search in given binary search range L to R
Auxiliary Space: O(1)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads