Minimize Array Sum with n Subtractions

Last Updated : 28 Jul, 2026

Given an array arr[] of n positive integers and an integer k, perform exactly n operations on the array. In each operation, any element from the array can be selected, and the same element can be selected multiple times.

  • For a selected element with value x, decrease its value by the larger of: floor(x / 10) (10% of its current value), or k
  • If the value of the selected element is less than k, reduce it to 0.

After performing exactly n operations, return the minimum possible sum of the array elements.

Examples:

Input: arr[] = [100, 15], k = 10
Output: 95
Explanation: Reduce 100 -> 90 -> 80 (both times by 10). Sum = 80 + 15 = 95.

Input: arr[] = [90, 100], k = 10
Output: 170
Explanation: Reduce 100 -> 90, then reduce one 90 -> 80. Sum = 80 + 90 = 170.

Try It Yourself
redirect icon

[Naive Approach] Simulate All Possible Operations - O(n ^ n * n) Time and O(n) Space

The idea is to try every possible choice of element in each of the n operations. For every operation, recursively select an element, apply the reduction, and continue until all operations are completed. Finally, return the minimum sum among all possible sequences of operations.

Working of Approach:

  • Perform recursion for exactly n operations.
  • In each operation, try reducing every array element.
  • Recur for the next operation after updating the selected element.
  • Backtrack to restore the original value.
  • Return the minimum sum obtained.
C++
#include <bits/stdc++.h>
using namespace std;

// Recursive function to find the minimum possible array sum
// after performing the remaining operations.
int findMinSum(vector<int> &arr, int k, int operationsDone)
{
    int n = arr.size();

    // If all operations are completed, return the current array sum.
    if (operationsDone == n)
    {
        int sum = 0;
        for (int x : arr)
            sum += x;

        return sum;
    }

    int res = INT_MAX;

    // Try selecting every array element for the current operation.
    for (int i = 0; i < n; i++)
    {
        int originalValue = arr[i];

        // Reduce the selected element according to the given rule.
        if (arr[i] <= k)
            arr[i] = 0;
        else
            arr[i] -= max(arr[i] / 10, k);

        // Recur for the next operation.
        res = min(res, findMinSum(arr, k, operationsDone + 1));

        // Restore the original value (backtracking).
        arr[i] = originalValue;
    }

    return res;
}

int minSum(vector<int> &arr, int k)
{
    return findMinSum(arr, k, 0);
}

int main()
{
    vector<int> arr = {90, 100};
    int k = 10;

    cout << minSum(arr, k);

    return 0;
}
Java
import java.util.Arrays;

public class GFG {
    // Recursive function to find the minimum possible array
    // sum after performing the remaining operations.
    static int findMinSum(int[] arr, int k,
                          int operationsDone)
    {
        int n = arr.length;

        // If all operations are completed, return the
        // current array sum.
        if (operationsDone == n) {
            int sum = 0;
            for (int x : arr)
                sum += x;

            return sum;
        }

        int res = Integer.MAX_VALUE;

        // Try selecting every array element for the current
        // operation.
        for (int i = 0; i < n; i++) {
            int originalValue = arr[i];

            // Reduce the selected element according to the
            // given rule.
            if (arr[i] <= k)
                arr[i] = 0;
            else
                arr[i] -= Math.max(arr[i] / 10, k);

            // Recur for the next operation.
            res = Math.min(
                res,
                findMinSum(arr, k, operationsDone + 1));

            // Restore the original value (backtracking).
            arr[i] = originalValue;
        }

        return res;
    }

    static int minSum(int[] arr, int k)
    {
        return findMinSum(arr, k, 0);
    }

    public static void main(String[] args)
    {
        int[] arr = { 90, 100 };
        int k = 10;

        System.out.println(minSum(arr, k));
    }
}
Python
def findMinSum(arr, k, operationsDone):
    n = len(arr)

    # If all operations are completed, return the current array sum.
    if operationsDone == n:
        return sum(arr)

    res = float('inf')

    # Try selecting every array element for the current operation.
    for i in range(n):
        originalValue = arr[i]

        # Reduce the selected element according to the given rule.
        if arr[i] <= k:
            arr[i] = 0
        else:
            arr[i] -= max(arr[i] // 10, k)

        # Recur for the next operation.
        res = min(res, findMinSum(arr, k, operationsDone + 1))

        # Restore the original value (backtracking).
        arr[i] = originalValue

    return res


def minSum(arr, k):
    return findMinSum(arr, k, 0)


# Driver Code
if __name__ == "__main__":
    arr = [90, 100]
    k = 10

    print(minSum(arr, k))
C#
using System;

public class GFG {
    // Recursive function to find the minimum possible array
    // sum after performing the remaining operations.
    static int FindMinSum(int[] arr, int k,
                          int operationsDone)
    {
        int n = arr.Length;

        // If all operations are completed, return the
        // current array sum.
        if (operationsDone == n) {
            int sum = 0;
            foreach(int x in arr) sum += x;

            return sum;
        }

        int res = int.MaxValue;

        // Try selecting every array element for the current
        // operation.
        for (int i = 0; i < n; i++) {
            int originalValue = arr[i];

            // Reduce the selected element according to the
            // given rule.
            if (arr[i] <= k)
                arr[i] = 0;
            else
                arr[i] -= Math.Max(arr[i] / 10, k);

            // Recur for the next operation.
            res = Math.Min(
                res,
                FindMinSum(arr, k, operationsDone + 1));

            // Restore the original value (backtracking).
            arr[i] = originalValue;
        }

        return res;
    }

    static int minSum(int[] arr, int k)
    {
        return FindMinSum(arr, k, 0);
    }

    public static void Main()
    {
        int[] arr = { 90, 100 };
        int k = 10;

        Console.WriteLine(minSum(arr, k));
    }
}
JavaScript
function findMinSum(arr, k, operationsDone)
{
    let n = arr.length;

    // If all operations are completed, return the current
    // array sum.
    if (operationsDone === n) {
        return arr.reduce((sum, val) => sum + val, 0);
    }

    let res = Number.MAX_SAFE_INTEGER;

    // Try selecting every array element for the current
    // operation.
    for (let i = 0; i < n; i++) {
        let originalValue = arr[i];

        // Reduce the selected element according to the
        // given rule.
        if (arr[i] <= k)
            arr[i] = 0;
        else
            arr[i] -= Math.max(Math.floor(arr[i] / 10), k);

        // Recur for the next operation.
        res = Math.min(
            res, findMinSum(arr, k, operationsDone + 1));

        // Restore the original value (backtracking).
        arr[i] = originalValue;
    }

    return res;
}

function minSum(arr, k) { return findMinSum(arr, k, 0); }

// Driver Code
let arr = [ 90, 100 ];
let k = 10;
console.log(minSum(arr, k));

Output
170

[Expected Approach] Greedy using Max Heap - O(n log n) Time and O(n) Space

The idea is to always reduce the largest element of the array. Since the reduction amount increases (or remains the same) with the element value, reducing the maximum element in every operation gives the minimum possible final sum. A max heap helps efficiently retrieve the largest element.

Working of Approach:

  • Insert all array elements into a max heap.
  • Perform exactly n operations.
  • Remove the largest element and reduce it according to the given rule.
  • Insert the updated value back if it is greater than 0.
  • Sum all remaining elements in the heap.

Let us understand with an example:
Input: arr[] = [90, 100], k = 10

  • Insert all elements into a max heap: [100, 90].
  • 1st operation: Pick the largest element 100, reduce it by 10 -> 90, and push it back. Heap becomes [90, 90].
  • 2nd operation: Pick one of the 90s, reduce it by 10 -> 80, and push it back. Heap becomes [90, 80].
  • Sum of the remaining elements = 90 + 80 = 170, which is the minimum possible sum after exactly 2 operations.
C++
#include <bits/stdc++.h>
using namespace std;

int minSum(vector<int> &arr, int k)
{
    priority_queue<int> pq;
    for (int x : arr)
        pq.push(x);

    int n = arr.size();

    // perform n operations, each time reducing the largest element
    for (int i = 0; i < n && !pq.empty(); i++)
    {
        int cur = pq.top();
        pq.pop();

        if (cur > k)
        {
            if (cur < 10 * k)
                cur -= k;
            else
                cur = (9 * cur) / 10;
            pq.push(cur);
        }
        // if cur <= k, it becomes 0 and is discarded (not pushed back)
    }

    int res = 0;
    while (!pq.empty())
    {
        res += pq.top();
        pq.pop();
    }

    return res;
}

int main()
{
    vector<int> arr = {90, 100};
    int k = 10;

    cout << minSum(arr, k);

    return 0;
}
Java
import java.util.*;

public class GFG {
    int minSum(int[] arr, int k)
    {
        PriorityQueue<Integer> pq = new PriorityQueue<>(
            Collections.reverseOrder());
        for (int x : arr)
            pq.add(x);

        int n = arr.length;

        // perform n operations, each time reducing the
        // largest element
        for (int i = 0; i < n && !pq.isEmpty(); i++) {
            int cur = pq.poll();

            if (cur > k) {
                if (cur < 10 * k)
                    cur -= k;
                else
                    cur = (9 * cur) / 10;
                pq.add(cur);
            }
            // if cur <= k, it becomes 0 and is discarded
            // (not pushed back)
        }

        int res = 0;
        while (!pq.isEmpty()) {
            res += pq.poll();
        }

        return res;
    }

    public static void main(String[] args)
    {
        GFG main = new GFG();
        int[] arr = { 90, 100 };
        int k = 10;

        System.out.println(main.minSum(arr, k));
    }
}
Python
import heapq


def minSum(arr, k):
    pq = [-x for x in arr]
    heapq.heapify(pq)

    n = len(arr)

    # perform n operations, each time reducing the largest element
    for i in range(n):
        if pq:
            cur = -heapq.heappop(pq)

            if cur > k:
                if cur < 10 * k:
                    cur -= k
                else:
                    cur = (9 * cur) // 10
                heapq.heappush(pq, -cur)
        # if cur <= k, it becomes 0 and is discarded (not pushed back)

    res = 0
    while pq:
        res -= heapq.heappop(pq)

    return res


if __name__ == '__main__':
    arr = [90, 100]
    k = 10

    print(minSum(arr, k))
C#
using System;
using System.Collections.Generic;

public class GFG {
    class MaxHeap {
        List<int> heap = new List<int>();

        public int Count
        {
            get { return heap.Count; }
        }

        public void Push(int val)
        {
            heap.Add(val);

            int i = heap.Count - 1;

            while (i > 0) {
                int p = (i - 1) / 2;

                if (heap[p] >= heap[i])
                    break;

                int temp = heap[p];
                heap[p] = heap[i];
                heap[i] = temp;

                i = p;
            }
        }

        public int Pop()
        {
            int top = heap[0];

            heap[0] = heap[heap.Count - 1];
            heap.RemoveAt(heap.Count - 1);

            int i = 0;

            while (true) {
                int largest = i;
                int left = 2 * i + 1;
                int right = 2 * i + 2;

                if (left < heap.Count
                    && heap[left] > heap[largest])
                    largest = left;

                if (right < heap.Count
                    && heap[right] > heap[largest])
                    largest = right;

                if (largest == i)
                    break;

                int temp = heap[i];
                heap[i] = heap[largest];
                heap[largest] = temp;

                i = largest;
            }

            return top;
        }
    }

    public int minSum(int[] arr, int k)
    {
        MaxHeap pq = new MaxHeap();

        foreach(int x in arr) pq.Push(x);

        int n = arr.Length;

        // Perform n operations, each time reducing the
        // largest element.
        for (int i = 0; i < n && pq.Count > 0; i++) {
            int cur = pq.Pop();

            if (cur > k) {
                if (cur < 10 * k)
                    cur -= k;
                else
                    cur = (9 * cur) / 10;

                pq.Push(cur);
            }
            // If cur <= k, it becomes 0 and is discarded.
        }

        int res = 0;
        while (pq.Count > 0)
            res += pq.Pop();

        return res;
    }

    public static void Main()
    {
        int[] arr = { 90, 100 };
        int k = 10;

        GFG obj = new GFG();
        Console.WriteLine(obj.minSum(arr, k));
    }
}
JavaScript
function minSum(arr, k)
{
    let pq = [];
    for (let x of arr) {
        pq.push(x);
    }
    pq.sort((a, b) => b - a);

    let n = arr.length;

    // perform n operations, each time reducing the largest
    // element
    for (let i = 0; i < n && pq.length > 0; i++) {
        let cur = pq.shift();

        if (cur > k) {
            if (cur < 10 * k)
                cur -= k;
            else
                cur = Math.floor((9 * cur) / 10);
            pq.push(cur);
            pq.sort((a, b) => b - a);
        }
        // if cur <= k, it becomes 0 and is discarded (not
        // pushed back)
    }

    let res = 0;
    while (pq.length > 0) {
        res += pq.shift();
    }

    return res;
}

// Driver Code
let arr = [ 90, 100 ];
let k = 10;

console.log(minSum(arr, k));

Output
170
Comment