Minimum operations to reduce array elements to zero using prefix operations and updates
Last Updated :
26 Mar, 2024
Given an array arr[] of length N. We can apply 2 types of operations on element of arr[]:
- Choose a prefix let say arr[0, i] (0 <= i < N) and decrement all elements of prefix by 1. This operation can only apply if all elements in the prefix > 0.
- Choose an element arr[i] (0 <= i < N) and update it to 0.
The task is to output the minimum number of operations required to reduce all the elements to 0.
Examples:
Input: N = 5, arr[] = {1, 1, 2, 2, 2}
Output: 4
Explanation: The operations are performed as below:
- Apply 1st type of operation on prefix arr[0, 4]. Then updated arr[] = {0, 0, 1, 1, 1}.
- Make arr[2], arr[3], and arr[4] to 0 by using 2nd type of operation one by one. This will require 3 operations.
In total 4 operations are required to make all elements 0. Therefore, output is 4.
Input: N = 9, arr[] = {5, 3, 3, 5, 2, 4, 5, 2, 1}
Output: 7
Explanation: It can be verified that the minimum number of operations will be 7. If they are used optimally.
Approach: Implement the idea below to solve the problem
This problem is observation based. Let us try to understand those observations:
- Observation 1: By using second operation we can make all elements 0 by using exactly N number of operations. In each operation we can set arr[i] for (1 <= i <= N) to 0. Thus, it must be noted that the minimum number of operations are bounded in the range [1, N].
- Observation 2: It will be helpful to apply 1st type of operation because it decrements all the elements of prefix by 1 in a single operation. But this operation can be applied only at elements arr[i] of prefix arr[0, i], where all elements are greater than 0. From here we get the intuition that, we should apply 1st type of operation on the prefix minimums. As prefix minimum is the minimum element of a prefix present at last index. So, using operation on such element won't make any element into 0 (which are left to the prefix min element). Therefore, create an array of prefix minimums and try to find the minimum number of operations for each prefix minimum in increasing order. For example, the prefix minimum let say M[] of arr[] = {3, 3, 4, 5, 2, 2, 2} will be M[] = {3, 3, 2, 2, 2}. It can be obtained by traversing arr[] and each iteration store element arr[i], if (arr[i] <= CurrentElement) and then set CurrentElement = arr[i]. Initially, CurrentElement is set to arr[0]. Now, we can see that obtained M[] is in decreasing order. So, we will find minimum number of operations from smaller Prefix minimums first. That's why we will process M[] from right side.
How to calculate minimum moves for each prefix minimum present in M[]:
- With X prefix moves, the maximum number of elements we can set to 0 is exactly the elements of M that are <= X. Let us take it in a variable Zx.
- Computing Zx: If X is processed in ascending order, Zx will correspond to some increasing suffix of M. Once Zx is known for a fixed X, we know that the total number of moves needed (including making X prefix moves) will be (X + (N - Zx)).
Therefore, final answer is the minimum of (X + N - Zx) across all (0 <= X < N).
Step-by-step algorithm:
- Declare the variable let say Mini to store the Prefix Minimum till now and initialize it with arr[0] initially.
- Declare an ArrayList let say M[] to store all the Prefix Minimums of arr[].
- Add Mini (First Prefix Minimum) into M[].
- Run a loop from i = 1 to i < N and follow below mentioned steps under the scope of loop:
- If (arr[i] <= Mini)
- Mini = arr[i]
- Add Mini into M[]
- Declare 3 variables let say X, Zx and Minn. Initialize Minn = N.
- Run a loop from i = (M.size() - 1) to i >= 0 and follow below mentioned steps under the scope of loop:
- If (X == M.get(i))
- Else
- X = M.get(i)
- Increment Zx.
- Minn = min (X + (N - Zx), Minn)
- Output Minn.
Below is the implementation of the algorithm:
C++
#include <iostream>
#include <vector>
using namespace std;
// Function to find the minimum operations
void Min_Ops(int N, int arr[]) {
// Variable to store the minimum element
// so far while traversing
int mini = arr[0];
// Vector to store the prefix minimums
vector<int> M;
// Adding first prefix minimum which is arr[0]
M.push_back(mini);
// Finding and storing prefix minimum in Vector
for (int i = 1; i < N; i++) {
if (arr[i] <= mini) {
mini = arr[i];
M.push_back(mini);
}
}
// finding the number of operations for each prefix
// minimum element
int x = 0, zx = 0, minn = N;
for (int i = M.size() - 1; i >= 0; i--) {
if (x == M[i]) {
zx++;
} else {
x = M[i];
zx++;
}
minn = min(x + (N - zx), minn);
}
cout << minn << endl;
}
// Driver Function
int main() {
// Inputs
int N = 9;
int arr[] = {5, 3, 3, 5, 2, 4, 5, 2, 1};
// Function call
Min_Ops(N, arr);
return 0;
}
// This code is contributed by akshitaguprzj3
Java
import java.util.ArrayList;
public class Main {
// Driver Function
public static void main(String[] args) {
// Inputs
int N = 9;
int[] arr = { 5, 3, 3, 5, 2, 4, 5, 2, 1 };
// Function call
minOps(N, arr);
}
public static void minOps(int N, int[] arr) {
// Variable to store the minimum element
// so far while traversing
int mini = arr[0];
// ArrayList to store the prefix minimums
ArrayList<Integer> M = new ArrayList<>();
// Adding first prefix minimum which is arr[0]
M.add(mini);
// Finding and storing prefix minimum in ArrayList
for (int i = 1; i < N; i++) {
if (arr[i] <= mini) {
mini = arr[i];
M.add(mini);
}
}
// Finding the number of operations for each prefix
// minimum element
int x = 0, zx = 0, minn = N;
for (int i = M.size() - 1; i >= 0; i--) {
if (x == M.get(i)) {
zx++;
} else {
x = M.get(i);
zx++;
}
minn = Math.min(x + (N - zx), minn);
}
System.out.println(minn);
}
}
C#
using System;
using System.Collections.Generic;
class Program {
// Function to find the minimum operations
static void Min_Ops(int N, int[] arr)
{
// Variable to store the minimum element
// so far while traversing
int mini = arr[0];
// List to store the prefix minimums
List<int> M = new List<int>();
// Adding first prefix minimum which is arr[0]
M.Add(mini);
// Finding and storing prefix minimum in List
for (int i = 1; i < N; i++) {
if (arr[i] <= mini) {
mini = arr[i];
M.Add(mini);
}
}
// finding the number of operations for each prefix
// minimum element
int x = 0, zx = 0, minn = N;
for (int i = M.Count - 1; i >= 0; i--) {
if (x == M[i]) {
zx++;
}
else {
x = M[i];
zx++;
}
minn = Math.Min(x + (N - zx), minn);
}
Console.WriteLine(minn);
}
// Driver Function
static void Main(string[] args)
{
// Inputs
int N = 9;
int[] arr = { 5, 3, 3, 5, 2, 4, 5, 2, 1 };
// Function call
Min_Ops(N, arr);
}
}
JavaScript
// Function to calculate minimum operations
function minOps(N, arr) {
// Variable to store the minimum element so far while traversing
let mini = arr[0];
// Array to store the prefix minimums
let M = [];
// Adding first prefix minimum which is arr[0]
M.push(mini);
// Finding and storing prefix minimums in the array
for (let i = 1; i < N; i++) {
if (arr[i] <= mini) {
mini = arr[i];
M.push(mini);
}
}
// Finding the number of operations for each prefix minimum element
let x = 0, zx = 0, minn = N;
for (let i = M.length - 1; i >= 0; i--) {
if (x === M[i]) {
zx++;
} else {
x = M[i];
zx++;
}
minn = Math.min(x + (N - zx), minn);
}
console.log(minn);
}
// Main function
function main() {
// Inputs
let N = 9;
let arr = [5, 3, 3, 5, 2, 4, 5, 2, 1];
// Function call
minOps(N, arr);
}
// Call the main function
main();
Python3
# Function to find the minimum operations
def min_ops(N, arr):
# Variable to store the minimum element
# so far while traversing
mini = arr[0]
# List to store the prefix minimums
M = [mini]
# Finding and storing prefix minimum in List
for i in range(1, N):
if arr[i] <= mini:
mini = arr[i]
M.append(mini)
# Finding the number of operations for each prefix minimum element
x, zx, minn = 0, 0, N
for i in range(len(M) - 1, -1, -1):
if x == M[i]:
zx += 1
else:
x = M[i]
zx += 1
minn = min(x + (N - zx), minn)
print(minn)
# Driver Function
if __name__ == "__main__":
# Inputs
N = 9
arr = [5, 3, 3, 5, 2, 4, 5, 2, 1]
# Function call
min_ops(N, arr)
Time Complexity: O(N), where N is the size of input array arr[].
Auxiliary Space: O(N), As ArrayList PreMins is used to store the Prefix Minimums.
Similar Reads
Minimum no. of operations required to make all Array Elements Zero Given an array of N elements and each element is either 1 or 0. You need to make all the elements of the array equal to 0 by performing the below operations: If an element is 1, You can change it's value equal to 0 then, if the next consecutive element is 1, it will automatically get converted to 0.
12 min read
Reduce all array elements to zero by performing given operations thrice Given an array arr[] of size N, the task is to convert every array element to 0 by applying the following operations exactly three times: Select a subarray.Increment every element of the subarray by the integer multiple of its length. Finally, print the first and last indices of the subarray involve
9 min read
Minimum number of given operations required to reduce the array to 0 element Given an array arr[] of N integers. The task is to find the minimum number of given operations required to reduce the array to 0 elements. In a single operation, any element can be chosen from the array and all of its multiples get removed including itself.Examples: Input: arr[] = {2, 4, 6, 3, 4, 6,
6 min read
Minimum cost to equal all elements of array using two operation Given an array arr[] of n positive integers. There are two operations allowed: Operation 1 : Pick any two indexes, increase value at one index by 1 and decrease value at another index by 1. It will cost a. Operation 2 : Pick any index and increase its value by 1. It will cost b. The task is to find
8 min read
Minimum operations to make product of adjacent element pair of prefix sum negative Given an array arr[ ] of size N, consider an array prefix[ ] where prefix[i] is the sum of the first i elements of arr. The task is to find the minimum number of operations required to modify the given array such that the product of any two adjacent elements in the prefix array is negative. In one o
7 min read