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++ 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 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 |
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))
|
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 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 |
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)