Maximize pair decrements required to reduce all array elements except one to 0
Last Updated :
14 Oct, 2023
Given an array arr[] consisting of N distinct elements, the task is to find the maximum number of pairs required to be decreased by 1 in each step, such that N – 1 array elements are reduced to 0 and the remaining array element is a non-negative integer.
Examples:
Input: arr[] = {1, 2, 3}
Output: 3
Explanation:
Decrease arr[1] and arr[2] by 1 modifies arr[] = {1, 1, 2}
Decrease arr[1] and arr[2] by 1 modifies arr[] = {1, 0, 1}
Decrease arr[0] and arr[2] by 1 modifies arr[] = {0, 0, 0}
Therefore, the maximum number of decrements required is 3.
Input: arr[] = {1, 2, 3, 4, 5}
Output: 7
Approach: The problem can be solved Greedily. Follow the steps below to solve the problem:
- Initialize a variable, say cntOp, to store maximum count of steps required to make (N – 1) elements of the array equal to 0.
- Create a priority queue, say PQ, to store the array elements.
- Traverse the array and insert the array elements into PQ.
- Now repeatedly extract the top 2 elements from the priority queue, decrease the value of both the elements by 1, again insert both the elements in priority queue and increment the cntOp by 1. This process continues while (N – 1) element of the PQ becomes equal to 0.
- Finally, print the value of cntOp
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int cntMaxOperationToMakeN_1_0( int arr[], int N)
{
int cntOp = 0;
priority_queue< int > PQ;
for ( int i = 0; i < N; i++) {
PQ.push(arr[i]);
}
while (PQ.size() > 1) {
int X = PQ.top();
PQ.pop();
int Y = PQ.top();
PQ.pop();
X--;
Y--;
if (X != 0) {
PQ.push(X);
}
if (Y != 0) {
PQ.push(Y);
}
cntOp += 1;
}
return cntOp;
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5 };
int N = sizeof (arr) / sizeof (arr[0]);
cout << cntMaxOperationToMakeN_1_0(arr, N);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int cntMaxOperationToMakeN_1_0( int [] arr, int N)
{
int cntOp = 0 ;
PriorityQueue<Integer> PQ = new PriorityQueue<Integer>((a, b) -> b - a);
for ( int i = 0 ; i < N; i++)
{
PQ.add(arr[i]);
}
while (PQ.size() > 1 )
{
int X = PQ.peek();
PQ.remove();
int Y = PQ.peek();
PQ.remove();
X--;
Y--;
if (X != 0 )
{
PQ.add(X);
}
if (Y != 0 )
{
PQ.add(Y);
}
cntOp += 1 ;
}
return cntOp;
}
public static void main(String[] args)
{
int [] arr = { 1 , 2 , 3 , 4 , 5 };
int N = arr.length;
System.out.print(cntMaxOperationToMakeN_1_0(arr, N));
}
}
|
Python3
def cntMaxOperationToMakeN_1_0(arr, N):
cntOp = 0
PQ = []
for i in range (N):
PQ.append(arr[i])
PQ = sorted (PQ)
while ( len (PQ) > 1 ):
X = PQ[ - 1 ]
del PQ[ - 1 ]
Y = PQ[ - 1 ]
del PQ[ - 1 ]
X - = 1
Y - = 1
if (X ! = 0 ):
PQ.append(X)
if (Y ! = 0 ):
PQ.append(Y)
cntOp + = 1
PQ = sorted (PQ)
return cntOp
if __name__ = = '__main__' :
arr = [ 1 , 2 , 3 , 4 , 5 ]
N = len (arr)
print (cntMaxOperationToMakeN_1_0(arr, N))
|
C#
using System;
using System.Collections.Generic;
class GFG {
static int cntMaxOperationToMakeN_1_0( int [] arr, int N)
{
int cntOp = 0;
List< int > PQ = new List< int >();
for ( int i = 0; i < N; i++) {
PQ.Add(arr[i]);
}
PQ.Sort();
PQ.Reverse();
while (PQ.Count > 1) {
int X = PQ[0];
PQ.RemoveAt(0);
int Y = PQ[0];
PQ.RemoveAt(0);
X--;
Y--;
if (X != 0) {
PQ.Add(X);
PQ.Sort();
PQ.Reverse();
}
if (Y != 0) {
PQ.Add(Y);
PQ.Sort();
PQ.Reverse();
}
cntOp += 1;
}
return cntOp;
}
static void Main() {
int [] arr = { 1, 2, 3, 4, 5 };
int N = arr.Length;
Console.WriteLine(cntMaxOperationToMakeN_1_0(arr, N));
}
}
|
Javascript
<script>
function cntMaxOperationToMakeN_1_0(arr, N)
{
let cntOp = 0;
let PQ = [];
for (let i = 0; i < N; i++) {
PQ.push(arr[i]);
}
PQ.sort( function (a, b){ return a - b});
PQ.reverse();
while (PQ.length > 1) {
let X = PQ[0];
PQ.shift();
let Y = PQ[0];
PQ.shift();
X--;
Y--;
if (X != 0) {
PQ.push(X);
PQ.sort( function (a, b){ return a - b});
PQ.reverse();
}
if (Y != 0) {
PQ.push(Y);
PQ.sort( function (a, b){ return a - b});
PQ.reverse();
}
cntOp += 1;
}
return cntOp;
}
let arr = [ 1, 2, 3, 4, 5 ];
let N = arr.length;
document.write(cntMaxOperationToMakeN_1_0(arr, N));
</script>
|
Time Complexity: O(N * log(N))
Auxiliary Space: O(N)
Approach: Using the Two Pointers approach
Algorithm steps:
- Sort the array arr in descending order using std::sort and the greater<int> comparator.
Initialize two pointers, left and right, where left starts at index 0 and right starts at index N – 2 (since we need to make (N – 1) elements equal to 0).
- Initialize a variable cntOp to keep track of the count of steps.
- Iterate until the left and right pointers meet or cross each other.
- In each iteration:
- Subtract 1 from both elements pointed to by the left and right pointers.
- If either element becomes non-positive:
- Move the left pointer to the right (increment it) if the left element becomes non-positive.
- Move the right pointer to the left (decrement it) if the right element becomes non-positive.
- Increment the count of steps cntOp by 1.
- After the iteration is complete, return the value of cntOp, which represents the maximum number of steps required to make (N – 1) elements equal to 0.
Below is the implementation of the above approach:
C++
#include <iostream>
#include <algorithm>
using namespace std;
int cntMaxOperationToMakeN_1_0( int arr[], int N)
{
sort(arr, arr + N, greater< int >());
int left = 0;
int right = N - 2;
int cntOp = 0;
while (left <= right) {
arr[left]--;
arr[right]--;
if (arr[left] <= 0)
left++;
if (arr[right] <= 0)
right--;
cntOp++;
}
return cntOp;
}
int main()
{
int arr[] = {1, 2, 3,4,5};
int N = sizeof (arr) / sizeof (arr[0]);
cout << cntMaxOperationToMakeN_1_0(arr, N);
return 0;
}
|
Java
import java.util.Arrays;
import java.util.Collections;
public class Main {
static int cntMaxOperationToMakeN_1_0( int arr[], int N) {
Arrays.sort(arr);
reverseArray(arr);
int left = 0 ;
int right = N - 2 ;
int cntOp = 0 ;
while (left <= right) {
arr[left]--;
arr[right]--;
if (arr[left] <= 0 )
left++;
if (arr[right] <= 0 )
right--;
cntOp++;
}
return cntOp;
}
static void reverseArray( int arr[]) {
int left = 0 ;
int right = arr.length - 1 ;
while (left < right) {
int temp = arr[left];
arr[left] = arr[right];
arr[right] = temp;
left++;
right--;
}
}
public static void main(String[] args) {
int arr[] = { 1 , 2 , 3 , 4 , 5 };
int N = arr.length;
System.out.println(cntMaxOperationToMakeN_1_0(arr, N));
}
}
|
Python3
def cntMaxOperationToMakeN_1_0(arr, N):
arr.sort(reverse = True )
left = 0
right = N - 2
cntOp = 0
while left < = right:
arr[left] - = 1
arr[right] - = 1
if arr[left] < = 0 :
left + = 1
if arr[right] < = 0 :
right - = 1
cntOp + = 1
return cntOp
arr = [ 1 , 2 , 3 , 4 , 5 ]
N = len (arr)
print (cntMaxOperationToMakeN_1_0(arr, N))
|
C#
using System;
using System.Linq;
namespace MaxOperationsToMakeZero
{
class Program
{
static int CountMaxOperationToMakeN_1_0( int [] arr, int N)
{
Array.Sort(arr, (x, y) => y.CompareTo(x));
int left = 0;
int right = N - 2;
int cntOp = 0;
while (left <= right)
{
arr[left]--;
arr[right]--;
if (arr[left] <= 0)
left++;
if (arr[right] <= 0)
right--;
cntOp++;
}
return cntOp;
}
static void Main( string [] args)
{
int [] arr = { 1, 2, 3, 4, 5 };
int N = arr.Length;
Console.WriteLine(CountMaxOperationToMakeN_1_0(arr, N));
}
}
}
|
Javascript
function cntMaxOperationToMakeN_1_0(arr, N) {
arr.sort((a, b) => b - a);
let left = 0;
let right = N - 2;
let cntOp = 0;
while (left <= right) {
arr[left]--;
arr[right]--;
if (arr[left] <= 0)
left++;
if (arr[right] <= 0)
right--;
cntOp++;
}
return cntOp;
}
const arr = [1, 2, 3, 4, 5];
const N = arr.length;
console.log(cntMaxOperationToMakeN_1_0(arr, N));
|
Time Complexity: O(N log N) , because of the sorting operation.
Auxiliary Space: O(1) because the algorithm only uses a constant amount of additional space for the pointers and variables.
Share your thoughts in the comments
Please Login to comment...