Open In App

Minimum operations to make Array elements 0 by decrementing pair or single element

Last Updated : 26 Sep, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] of size N, the task is to find the minimum number of operations required to reduce all three elements of the array to zero. Following operations are allowed:

  • Reduce 2 different array elements by one.
  • Reduce a single array element by one.

Example:

Input: arr[] = {1, 2, 3}, N = 3
Output: 3
Explanation : Operation 1: reduce 3 and 2 to get {1, 1, 2}
Operation 2: reduce 1 and 2 to get {1, 0, 1}
Operation 3: reduce both 1s to get {0, 0, 0}

Input: arr[] = {5, 1, 2, 9, 8}, N = 5
Output: 13

Approach:

This problem can be solved using greedy approach. The idea is to reduce the 2 largest elements at a time or (if not possible) 1 at a time.  As we need the largest elements in each step, we can use a max heap.

The following steps can be taken to solve this approach:

  • Initiate a count variable as 0.
  • Insert all the elements in a max heap.
    • Reduce the two largest elements.
    • Insert the reduced values again into the heap.
  • Repeat above mentioned steps until all array elements become zero and increase the count at each iteration.
  • Stop when all array elements are zero.

Below is the implementation of the above approach:

C++




#include <bits/stdc++.h>
using namespace std;
 
// C++ program to reduce array to zero in minimum steps
int reduceArray(int arr[], int N)
    {
         int count = 0;
        priority_queue<int>pq;
   
        for (int i = 0; i < N; i++) {
            pq.push(arr[i] * -1);
        }
        while (pq.size() > 1) {
             
            int temp1 = pq.top();
            pq.pop();
             
            int temp2 = pq.top();
          pq.pop();
            count++;
            temp1++;
            temp2++;
            if (temp1 != 0)
                pq.push(temp1);
            if (temp2 != 0)
                pq.push(temp2);
        }
        if (pq.size() > 0){
           
            count -= pq.top();
          pq.pop();
        }
        return count-1;
    }
 
 // Driver Code
int main() {
    int arr[] = { 1, 2, 3 };
        int N = 3;
        int count = reduceArray(arr, N);
        cout << count;
    return 0;
}
 
// This code is contributed by satwik4409.


Java




// Java program to reduce array to zero in minimum steps
import java.util.*;
 
class GFG {
 
    public static int reduceArray(int arr[], int N)
    {
 
        int count = 0;
        PriorityQueue<Integer> pq = new PriorityQueue<>();
 
        for (int i = 0; i < N; i++) {
            pq.add(arr[i] * -1);
        }
        while (pq.size() > 1) {
            int temp1 = pq.poll();
            int temp2 = pq.poll();
            count++;
            temp1++;
            temp2++;
            if (temp1 != 0)
                pq.add(temp1);
            if (temp2 != 0)
                pq.add(temp2);
        }
        if (pq.size() > 0)
            count -= pq.poll();
        return count;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int arr[] = { 1, 2, 3 };
        int N = 3;
        int count = reduceArray(arr, N);
        System.out.println(count);
    }
}


Python3




# Python program to reduce array to zero in minimum steps
from queue import PriorityQueue
 
def reduceArray(arr, N):
    count = 0
    pq = PriorityQueue()
 
    for i in range(N):
        pq.put(arr[i] * -1)
 
    while (pq.qsize() > 1):
        temp1 = pq.get()
        temp2 = pq.get()
        count += 1
        temp1 += 1
        temp2 += 1
        if (temp1 != 0):
            pq.put(temp1)
        if (temp2 != 0):
            pq.put(temp2)
 
    if (pq.qsize() > 0):
        count -= pq.get()
    return count
 
# Driver Code
arr = [1, 2, 3]
N = 3
count = reduceArray(arr, N)
print(count)
 
# This code is contributed by hrithikgarg03188.


C#




// C# implementation of above approach
using System;
using System.Collections.Generic;
 
class GFG {
 
   public static int reduceArray(int[] arr, int N)
    {
  
        int count = 0;
        List<int> pq = new List<int>();
  
        for (int i = 0; i < N; i++) {
            pq.Add(arr[i] * -1);
        }
        while (pq.Count > 1) {
             
            int temp1 = pq[0];
            pq.RemoveAt(0);
            int temp2 = pq[0];
            pq.RemoveAt(0);
            count++;
            temp1++;
            temp2++;
            if (temp1 != 0)
                pq.Add(temp1);
            if (temp2 != 0)
                pq.Add(temp2);
        }
        if (pq.Count > 0)
            count -= pq[0];
            pq.RemoveAt(0);
        return count-1;
    }
  
  // Driver Code
  public static void Main()
  {
    int[] arr = { 1, 2, 3 };
    int N = 3;
    int count = reduceArray(arr, N);
    Console.Write(count);
  }
}
 
// This code is contributed by sanjoy_62.


Javascript




<script>
 
// Javascript Priority Queue implementation
function PriorityQueue () {
    let collection = [];
    this.printCollection = function() {
      (console.log(collection));
    };
    this.enqueue = function(element){
        if (this.isEmpty()){
            collection.push(element);
        } else {
            let added = false;
            for (let i=0; i<collection.length; i++){
                 if (element[1] < collection[i][1]){ //checking priorities
                    collection.splice(i,0,element);
                    added = true;
                    break;
                }
            }
            if (!added){
                collection.push(element);
            }
        }
    };
    this.dequeue = function() {
        let value = collection.shift();
        return value[0];
    };
    this.top = function() {
        return collection[0];
    };
    this.size = function() {
        return collection.length;
    };
    this.isEmpty = function() {
        return (collection.length === 0);
    };
}
 
// Javascript program to reduce array to zero in minimum steps
 
function reduceArray(arr, N)
    {
         let count = 0;
        let pq = new PriorityQueue();
   
        for (let i = 0; i < N; i++) {
            pq.enqueue(arr[i] * -1);
        }
        while (pq.size() > 1) {
             
            let temp1 = pq.top();
            pq.dequeue();
             
            let temp2 = pq.top();
          pq.dequeue();
            count++;
            temp1++;
            temp2++;
            if (temp1 != 0)
                pq.enqueue(temp1);
            if (temp2 != 0)
                pq.enqueue(temp2);
        }
        if (pq.size() > 0){
           
            count -= pq.top();
          pq.dequeue();
        }
        return count-1;
    }
 
 // Driver Code
    let arr = [ 1, 2, 3 ];
    let N = 3;
    let count = reduceArray(arr, N);
    console.log(count);
     
    // This code is contributed by akashish__
 
</script>


Output

3


Time Complexity: O(N * logN)
Auxiliary Space: O(N)

Another Approach:

  • Initialize a variable ‘operations’ to 0, which will keep track of the number of operations required to reduce the array to all zeroes.
  • Use a while loop to repeatedly perform the following steps until all elements of the array become zero:
  • Find the maximum element(s) of the array. To do this, initialize ‘max_val’ to negative infinity, ‘max_idx’ to -1, and ‘max_cnt’ to 0. Then, iterate over the array and for each element, check if it is greater than ‘max_val’. If it is, update ‘max_val’ to the value of that element, ‘max_idx’ to the index of that element, and ‘max_cnt’ to 1. If the element is equal to ‘max_val’, increment ‘max_cnt’ by 1. At the end of the loop, we will have the maximum value(s) of the array, their index(es), and the number of times the maximum value(s) occur in the array.
  • If ‘max_val’ is equal to zero, break out of the while loop, as all elements of the array have become zero.
  • If ‘max_cnt’ is greater than 1, reduce any two of the maximum elements. If ‘max_cnt’ is equal to 2, iterate over the array again and find the two elements with value ‘max_val’. Reduce one of them by 1 and reduce the other one by 1 as well. Increment ‘operations’ by 1. If ‘max_cnt’ is greater than 2, simply reduce ‘max_val’ by 2 and increment ‘operations’ by 1.
  • If ‘max_cnt’ is equal to 1, reduce the maximum element with the second maximum element. To do this, initialize ‘second_max_val’ to negative infinity and ‘second_max_idx’ to -1. Then, iterate over the array again and for each element, check if it is greater than ‘second_max_val’ and not equal to ‘max_val’. If it is, update ‘second_max_val’ to the value of that element and ‘second_max_idx’ to the index of that element. At the end of the loop, we will have the second maximum value of the array and its index. Reduce ‘max_val’ by 1 and reduce ‘second_max_val’ by 1. Increment ‘operations’ by 1.
  • Once the while loop has completed, return the value of ‘operations’.

Below is the implementation of the above approach:

C++




#include <bits/stdc++.h>
 
using namespace std;
 
int reduceArray(int arr[], int N)
{
 
    int operations = 0;
 
    while (true) {
 
        // Find the maximum element(s)
 
        int max_val = INT_MIN, max_idx = -1, max_cnt = 0;
 
        for (int i = 0; i < N; i++) {
 
            if (arr[i] > max_val) {
 
                max_val = arr[i];
 
                max_idx = i;
 
                max_cnt = 1;
            }
            else if (arr[i] == max_val) {
 
                max_cnt++;
            }
        }
 
        if (max_val == 0) {
 
            // All elements become zero
 
            break;
        }
 
        if (max_cnt > 1) {
 
            // Reduce any two of the maximum elements
 
            if (max_cnt == 2) {
 
                for (int i = 0; i < N; i++) {
 
                    if (arr[i] == max_val && i != max_idx) {
 
                        arr[i]--;
 
                        arr[max_idx]--;
 
                        operations++;
 
                        break;
                    }
                }
            }
            else {
 
                arr[max_idx] -= 2;
 
                operations++;
            }
        }
        else {
 
            // Reduce the maximum element with the second
            // maximum element
 
            int second_max_val = INT_MIN,
                second_max_idx = -1;
 
            for (int i = 0; i < N; i++) {
 
                if (arr[i] > second_max_val
                    && i != max_idx) {
 
                    second_max_val = arr[i];
 
                    second_max_idx = i;
                }
            }
 
            arr[max_idx]--;
 
            arr[second_max_idx]--;
 
            operations++;
        }
    }
 
    return operations;
 
} // Driver Code
 
int main()
{
 
    int arr[] = { 1, 2, 3 };
 
    int N = 3;
 
    int count = reduceArray(arr, N);
 
    cout << count;
 
    return 0;
}


Java




import java.util.Arrays;
 
public class Main {
 
    // Function to reduce the array
    static int reduceArray(int[] arr, int N) {
        int operations = 0;
 
        while (true) {
            // Find the maximum element(s)
            int max_val = Integer.MIN_VALUE, max_idx = -1, max_cnt = 0;
 
            for (int i = 0; i < N; i++) {
                if (arr[i] > max_val) {
                    max_val = arr[i];
                    max_idx = i;
                    max_cnt = 1;
                } else if (arr[i] == max_val) {
                    max_cnt++;
                }
            }
 
            if (max_val == 0) {
                // All elements become zero
                break;
            }
 
            if (max_cnt > 1) {
                // Reduce any two of the maximum elements
                if (max_cnt == 2) {
                    for (int i = 0; i < N; i++) {
                        if (arr[i] == max_val && i != max_idx) {
                            arr[i]--;
                            arr[max_idx]--;
                            operations++;
                            break;
                        }
                    }
                } else {
                    arr[max_idx] -= 2;
                    operations++;
                }
            } else {
                // Reduce the maximum element with the second maximum element
                int second_max_val = Integer.MIN_VALUE, second_max_idx = -1;
 
                for (int i = 0; i < N; i++) {
                    if (arr[i] > second_max_val && i != max_idx) {
                        second_max_val = arr[i];
                        second_max_idx = i;
                    }
                }
 
                arr[max_idx]--;
                arr[second_max_idx]--;
                operations++;
            }
        }
 
        return operations;
    }
 
    // Driver Code
    public static void main(String[] args) {
        int[] arr = { 1, 2, 3 };
        int N = 3;
 
        int count = reduceArray(arr, N);
 
        System.out.println(count);
    }
}


Python3




def reduceArray(arr, N):
    operations = 0
 
    while True:
        # Find the maximum element(s)
        max_val = float('-inf')
        max_idx = -1
        max_cnt = 0
 
        for i in range(N):
            if arr[i] > max_val:
                max_val = arr[i]
                max_idx = i
                max_cnt = 1
            elif arr[i] == max_val:
                max_cnt += 1
 
        if max_val == 0:
            # All elements become zero
            break
 
        if max_cnt > 1:
            # Reduce any two of the maximum elements
            if max_cnt == 2:
                for i in range(N):
                    if arr[i] == max_val and i != max_idx:
                        arr[i] -= 1
                        arr[max_idx] -= 1
                        operations += 1
                        break
            else:
                arr[max_idx] -= 2
                operations += 1
        else:
            # Reduce the maximum element with the second maximum element
            second_max_val = float('-inf')
            second_max_idx = -1
 
            for i in range(N):
                if arr[i] > second_max_val and i != max_idx:
                    second_max_val = arr[i]
                    second_max_idx = i
 
            arr[max_idx] -= 1
            arr[second_max_idx] -= 1
            operations += 1
 
    return operations
 
# Driver Code
arr = [1, 2, 3]
N = 3
count = reduceArray(arr, N)
print(count)


C#




using System;
 
class Program {
 
  static int ReduceArray(int[] arr, int N)
  {
    int operations = 0;
 
    while (true) {
      int max_val = int.MinValue, max_idx = -1,
      max_cnt = 0;
 
      for (int i = 0; i < N; i++) {
        if (arr[i] > max_val) {
          max_val = arr[i];
          max_idx = i;
          max_cnt = 1;
        }
        else if (arr[i] == max_val) {
          max_cnt++;
        }
      }
 
      if (max_val == 0) {
        break;
      }
 
      if (max_cnt > 1) {
        if (max_cnt == 2) {
          for (int i = 0; i < N; i++) {
            if (arr[i] == max_val
                && i != max_idx) {
              arr[i]--;
              arr[max_idx]--;
              operations++;
              break;
            }
          }
        }
        else {
          arr[max_idx] -= 2;
          operations++;
        }
      }
      else {
        int second_max_val = int.MinValue,
        second_max_idx = -1;
        for (int i = 0; i < N; i++) {
          if (arr[i] > second_max_val
              && i != max_idx) {
            second_max_val = arr[i];
            second_max_idx = i;
          }
        }
 
        arr[max_idx]--;
        arr[second_max_idx]--;
        operations++;
      }
    }
 
    return operations;
  }
 
  static void Main(string[] args)
  {
    int[] arr = { 1, 2, 3 };
    int N = arr.Length;
    int count = ReduceArray(arr, N);
    Console.WriteLine(count);
  }
}


Javascript




function reduceArray(arr, N)
{
 
    let operations = 0;
    while (true) {
 
        // Find the maximum element(s)
        let max_val = -Infinity, max_idx = -1, max_cnt = 0;
        for (let i = 0; i < N; i++)
        {
            if (arr[i] > max_val) {
                max_val = arr[i];
                max_idx = i;
                max_cnt = 1;
            }
            else if (arr[i] === max_val) {
                max_cnt++;
            }
        }
 
        if (max_val === 0) {
 
            // All elements become zero
 
            break;
        }
 
        if (max_cnt > 1) {
 
            // Reduce any two of the maximum elements
            if (max_cnt === 2) {
                for (let i = 0; i < N; i++) {
                    if (arr[i] === max_val && i !== max_idx) {
                        arr[i]--;
                        arr[max_idx]--;
                        operations++;
                        break;
                    }
                }
            }
            else {
 
                arr[max_idx] -= 2;
 
                operations++;
            }
        }
        else {
 
            // Reduce the maximum element with the second
            // maximum element
            let second_max_val = -Infinity,
                second_max_idx = -1;
            for (let i = 0; i < N; i++) {
                if (arr[i] > second_max_val
                    && i !== max_idx) {
                    second_max_val = arr[i];
                    second_max_idx = i;
                }
            }
 
            arr[max_idx]--;
            arr[second_max_idx]--;
            operations++;
        }
    }
    return operations;
 
}
 
// Driver Code
let arr = [1, 2, 3];
let N = 3;
let count = reduceArray(arr, N);
console.log(count);


Output

3


Time Complexity: O(N)

Auxiliary Space: O(1)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads