Maximize pair decrements required to reduce all array elements except one to 0

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++
// C++ program to implement// the above approach#include <bits/stdc++.h>using namespace std;Â
// Function to count maximum number of steps// to make (N - 1) array elements to 0int cntMaxOperationToMakeN_1_0(int arr[], int N){Â
    // Stores maximum count of steps to make    // (N - 1) elements equal to 0    int cntOp = 0;Â
    // Stores array elements    priority_queue<int> PQ;Â
    // Traverse the array    for (int i = 0; i < N; i++) {Â
        // Insert arr[i] into PQ        PQ.push(arr[i]);    }Â
    // Extract top 2 elements from the array    // while (N - 1) array elements become 0    while (PQ.size() > 1) {Â
        // Stores top element        // of PQ        int X = PQ.top();Â
        // Pop the top element        // of PQ.        PQ.pop();Â
        // Stores top element        // of PQ        int Y = PQ.top();Â
        // Pop the top element        // of PQ.        PQ.pop();Â
        // Update X        X--;Â
        // Update Y        Y--;Â
        // If X is not equal to 0        if (X != 0) {Â
            // Insert X into PQ            PQ.push(X);        }Â
        // if Y is not equal        // to 0        if (Y != 0) {Â
            // Insert Y            // into PQ            PQ.push(Y);        }Â
        // Update cntOp        cntOp += 1;    }Â
    return cntOp;}Â
// Driver Codeint main(){Â
    int arr[] = { 1, 2, 3, 4, 5 };Â
    int N = sizeof(arr) / sizeof(arr[0]);Â
    cout << cntMaxOperationToMakeN_1_0(arr, N);Â
    return 0;} |
Java
// Java program to implement// the above approachimport java.util.*;Â
class GFG{     // Function to count maximum number of steps// to make (N - 1) array elements to 0static int cntMaxOperationToMakeN_1_0(int[] arr, int N){         // Stores maximum count of steps to make    // (N - 1) elements equal to 0    int cntOp = 0;         // Stores array elements    PriorityQueue<Integer> PQ = new PriorityQueue<Integer>((a, b) -> b - a);         // Traverse the array    for(int i = 0; i < N; i++)    {                 // Insert arr[i] into PQ        PQ.add(arr[i]);    }         // Extract top 2 elements from the array    // while (N - 1) array elements become 0    while (PQ.size() > 1)     {                 // Stores top element        // of PQ        int X = PQ.peek();                 // Pop the top element        // of PQ.        PQ.remove();                 // Stores top element        // of PQ        int Y = PQ.peek();                 // Pop the top element        // of PQ.        PQ.remove();                 // Update X        X--;                 // Update Y        Y--;                 // If X is not equal to 0        if (X != 0)         {                         // Insert X into PQ            PQ.add(X);        }                 // if Y is not equal        // to 0        if (Y != 0)         {                         // Insert Y            // into PQ            PQ.add(Y);        }                 // Update cntOp        cntOp += 1;    }    return cntOp;}Â
// Driver codepublic static void main(String[] args){Â Â Â Â int[] arr = { 1, 2, 3, 4, 5 };Â Â Â Â int N = arr.length;Â
    System.out.print(cntMaxOperationToMakeN_1_0(arr, N));}}Â
// This code is contributed by susmitakundugoaldanga |
Python3
# Python3 program to implement# the above approachÂ
# Function to count maximum number of steps# to make (N - 1) array elements to 0def cntMaxOperationToMakeN_1_0(arr, N):Â
    # Stores maximum count of steps to make    # (N - 1) elements equal to 0    cntOp = 0Â
    # Stores array elements    PQ = []Â
    # Traverse the array    for i in range(N):Â
        # Insert arr[i] into PQ        PQ.append(arr[i])    PQ = sorted(PQ)Â
    # Extract top 2 elements from the array    # while (N - 1) array elements become 0    while (len(PQ) > 1):Â
        # Stores top element        # of PQ        X = PQ[-1]Â
        # Pop the top element        # of PQ.        del PQ[-1]Â
        # Stores top element        # of PQ        Y = PQ[-1]Â
        # Pop the top element        # of PQ.        del PQ[-1]Â
        # Update X        X -= 1Â
        # Update Y        Y -= 1Â
        # If X is not equal to 0        if (X != 0):Â
            # Insert X into PQ            PQ.append(X)Â
        # if Y is not equal        # to 0        if (Y != 0):Â
            # Insert Y            # into PQ            PQ.append(Y)Â
        # Update cntOp        cntOp += 1        PQ = sorted(PQ)    return cntOpÂ
# Driver Codeif __name__ == '__main__':Â
    arr = [1, 2, 3, 4, 5]    N = len(arr)    print (cntMaxOperationToMakeN_1_0(arr, N))Â
    # This code is contributed by mohit kumar 29. |
C#
// C# program to implement// the above approachusing System;using System.Collections.Generic;class GFG {Â
  // Function to count maximum number of steps  // to make (N - 1) array elements to 0  static int cntMaxOperationToMakeN_1_0(int[] arr, int N)  {Â
    // Stores maximum count of steps to make    // (N - 1) elements equal to 0    int cntOp = 0;Â
    // Stores array elements    List<int> PQ = new List<int>();Â
    // Traverse the array    for (int i = 0; i < N; i++) {Â
      // Insert arr[i] into PQ      PQ.Add(arr[i]);    }Â
    PQ.Sort();    PQ.Reverse();Â
    // Extract top 2 elements from the array    // while (N - 1) array elements become 0    while (PQ.Count > 1) {Â
      // Stores top element      // of PQ      int X = PQ[0];Â
      // Pop the top element      // of PQ.      PQ.RemoveAt(0);Â
      // Stores top element      // of PQ      int Y = PQ[0];Â
      // Pop the top element      // of PQ.      PQ.RemoveAt(0);Â
      // Update X      X--;Â
      // Update Y      Y--;Â
      // If X is not equal to 0      if (X != 0) {Â
        // Insert X into PQ        PQ.Add(X);        PQ.Sort();        PQ.Reverse();      }Â
      // if Y is not equal      // to 0      if (Y != 0) {Â
        // Insert Y        // into PQ        PQ.Add(Y);        PQ.Sort();        PQ.Reverse();      }Â
      // Update cntOp      cntOp += 1;    }Â
    return cntOp;  }Â
  // Driver code  static void Main() {    int[] arr = { 1, 2, 3, 4, 5 };Â
    int N = arr.Length;Â
    Console.WriteLine(cntMaxOperationToMakeN_1_0(arr, N));  }}Â
// This code is contributed by divyesh072019 |
Javascript
<script>    // Javascript program to implement the above approach         // Function to count maximum number of steps    // to make (N - 1) array elements to 0    function cntMaxOperationToMakeN_1_0(arr, N)    {Â
      // Stores maximum count of steps to make      // (N - 1) elements equal to 0      let cntOp = 0;Â
      // Stores array elements      let PQ = [];Â
      // Traverse the array      for (let i = 0; i < N; i++) {Â
        // Insert arr[i] into PQ        PQ.push(arr[i]);      }Â
      PQ.sort(function(a, b){return a - b});      PQ.reverse();Â
      // Extract top 2 elements from the array      // while (N - 1) array elements become 0      while (PQ.length > 1) {Â
        // Stores top element        // of PQ        let X = PQ[0];Â
        // Pop the top element        // of PQ.        PQ.shift();Â
        // Stores top element        // of PQ        let Y = PQ[0];Â
        // Pop the top element        // of PQ.        PQ.shift();Â
        // Update X        X--;Â
        // Update Y        Y--;Â
        // If X is not equal to 0        if (X != 0) {Â
          // Insert X into PQ          PQ.push(X);          PQ.sort(function(a, b){return a - b});          PQ.reverse();        }Â
        // if Y is not equal        // to 0        if (Y != 0) {Â
          // Insert Y          // into PQ          PQ.push(Y);          PQ.sort(function(a, b){return a - b});          PQ.reverse();        }Â
        // Update cntOp        cntOp += 1;      }Â
      return cntOp;    }         let arr = [ 1, 2, 3, 4, 5 ];    let N = arr.length;    document.write(cntMaxOperationToMakeN_1_0(arr, N));         // This code is contributed by mukesh07.</script> |
7
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++
//C++ code for the above approach#include <iostream>#include <algorithm>using namespace std;Â
// Function to count maximum number of steps// to make (N - 1) array elements equal to 0int cntMaxOperationToMakeN_1_0(int arr[], int N){    // Sort the array in descending order    sort(arr, arr + N, greater<int>());Â
    // Initialize two pointers    int left = 0;    int right = N - 2; // (N - 1) elements to make 0Â
    // Count the number of steps    int cntOp = 0;Â
    // Perform steps until left and right pointers meet    while (left <= right) {        // Subtract 1 from both elements        arr[left]--;        arr[right]--;Â
        // If either element becomes non-positive,        // move the pointer accordingly        if (arr[left] <= 0)            left++;        if (arr[right] <= 0)            right--;Â
        // Increment the count of steps        cntOp++;    }Â
    return cntOp;}Â
// Driver Codeint 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 {Â
    // Function to count maximum number of steps    // to make (N - 1) array elements equal to 0    static int cntMaxOperationToMakeN_1_0(int arr[], int N) {        // Sort the array in descending order        Arrays.sort(arr);        reverseArray(arr);Â
        // Initialize two pointers        int left = 0;        int right = N - 2; // (N - 1) elements to make 0Â
        // Count the number of steps        int cntOp = 0;Â
        // Perform steps until left and right pointers meet        while (left <= right) {            // Subtract 1 from both elements            arr[left]--;            arr[right]--;Â
            // If either element becomes non-positive,            // move the pointer accordingly            if (arr[left] <= 0)                left++;            if (arr[right] <= 0)                right--;Â
            // Increment the count of steps            cntOp++;        }Â
        return cntOp;    }Â
    // Function to reverse the array    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--;        }    }Â
    // Driver Code    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):    # Sort the array in descending order    arr.sort(reverse=True)Â
    # Initialize two pointers    left = 0    right = N - 2 # (N - 1) elements to make 0Â
    # Count the number of steps    cntOp = 0Â
    # Perform steps until left and right pointers meet    while left <= right:        # Subtract 1 from both elements        arr[left] -= 1        arr[right] -= 1Â
        # If either element becomes non-positive,        # move the pointer accordingly        if arr[left] <= 0:            left += 1        if arr[right] <= 0:            right -= 1Â
        # Increment the count of steps        cntOp += 1Â
    return cntOpÂ
# Driver Codearr = [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)        {            // Sort the array in descending order            Array.Sort(arr, (x, y) => y.CompareTo(x));Â
            // Initialize two pointers            int left = 0;            int right = N - 2; // (N - 1) elements to make 0Â
            // Count the number of steps            int cntOp = 0;Â
            // Perform steps until left and right pointers meet            while (left <= right)            {                // Subtract 1 from both elements                arr[left]--;                arr[right]--;Â
                // If either element becomes non-positive,                // move the pointer accordingly                if (arr[left] <= 0)                    left++;                if (arr[right] <= 0)                    right--;Â
                // Increment the count of steps                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 to count maximum number of steps// to make (N - 1) array elements equal to 0function cntMaxOperationToMakeN_1_0(arr, N) {    // Sort the array in descending order    arr.sort((a, b) => b - a);Â
    // Initialize two pointers    let left = 0;    let right = N - 2; // (N - 1) elements to make 0Â
    // Count the number of steps    let cntOp = 0;Â
    // Perform steps until left and right pointers meet    while (left <= right) {        // Subtract 1 from both elements        arr[left]--;        arr[right]--;Â
        // If either element becomes non-positive,        // move the pointer accordingly        if (arr[left] <= 0)            left++;        if (arr[right] <= 0)            right--;Â
        // Increment the count of steps        cntOp++;    }Â
    return cntOp;}Â
// Driver Codeconst arr = [1, 2, 3, 4, 5];const N = arr.length;Â
console.log(cntMaxOperationToMakeN_1_0(arr, N)); |
7
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.Â
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!



