Open In App

Maximum subtraction of Array values from K to make it 0 or minimum

Improve
Improve
Like Article
Like
Save
Share
Report

Given two arrays A[] and B[] (B[i] < A[i]) of size N each and an integer K, the task is to perform the operation of (K – A[i] + B[i]) the maximum number of times such that K becomes 0 or as minimum as possible.

Note: At no moment an operation will be performed such that K becomes negative i.e. the operation cannot be performed if K – A[i] is negative and any index can be selected as many times as possible.

Examples:

Input: N = 3, K = 3, A[] = {2, 3, 4}, B[] = {1, 1, 1}
Output: 2
Explanation: For maximum turns,  
Choose A[0] and B[0], so  K = 3 – 2 + 1 = 2.
Choose A[0] and B[0], so  K = 2 – 2 + 1 = 1.
No other operation is possible. So max turns = 2.

Input: N = 2, K = 10, A[] = {5, 4} B[] ={1, 2}
Output: 4

 

Approach: The problem can be solved based on the following idea:

For performing the operation maximum number of times, always keep picking the indices (say i) so that A[i] – B[i] is minimum.

Say such value is A[i] and B[i], so the maximum performed operations for that index are (K – B[i]) / (A[i] – B[i]) [Here K – B[i] to avoid the last operation where K-A[i] is negative]

Follow the steps mentioned below to implement the idea:

  • Create an array (say v) to store the values in the form of (A[i] – B[i], A[i]).
  • Sort the array in increasing order on the basis of (A[i] – B[i]).
  • Loop from i = 0 to N-1:
    • If K – second value of v[i] is not negative then use the above formula to find its contribution (say x).
    • Increment the count by x.
  • Return the final count as the answer.

Below is the implementation of the above approach.

C++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to calculate the maximum operations
int MakeitMin(int n, int k, int a[], int b[])
{
    // Create a vector pair to store the difference
    vector<pair<int, int> > v(n);
    for (int i = 0; i < n; i++)
        v[i] = { a[i] - b[i], a[i] };
 
    // Sort it accordingly
    sort(v.begin(), v.end());
    int ans = 0;
    for (int i = 0; i < n; i++) {
 
        // Check if we can perform that turn or not
        if (v[i].second > k)
            continue;
 
        // If we can perform, calculate max times
        // we can perform that turn
        // and add it to ans
        int diff
            = (k - (v[i].second - v[i].first)) / v[i].first;
        ans += diff;
 
        // Reduce the k value
        k -= (diff * v[i].first);
    }
    return ans;
}
 
// Driver Code
int main()
{
    int N = 2, K = 10;
    int A[] = { 5, 4 };
    int B[] = { 1, 2 };
    cout << MakeitMin(N, K, A, B);
    return 0;
}


Java




// Java code to implement the approach
import java.io.*;
import java.util.*;
 
class GFG {
    // Function to calculate the maximum operations
    public static int MakeitMin(int n, int k, int a[],
                                int b[])
    {
        // Create a array of pairs to store the difference
        int v[][] = new int[n][2];
        for (int i = 0; i < n; i++) {
            v[i][0] = a[i] - b[i];
            v[i][1] = a[i];
        }
 
        // Sort it accordingly
        Arrays.sort(v,
                    (x, y) -> Integer.compare(x[0], y[0]));
        int ans = 0;
        for (int i = 0; i < n; i++) {
 
            // Check if we can perform that turn or not
            if (v[i][1] > k)
                continue;
 
            // If we can perform, calculate max times
            // we can perform that turn
            // and add it to ans
            int diff = (k - (v[i][1] - v[i][0])) / v[i][0];
            ans += diff;
 
            // Reduce the k value
            k -= (diff * v[i][0]);
        }
        return ans;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int N = 2, K = 10;
        int A[] = { 5, 4 };
        int B[] = { 1, 2 };
        System.out.print(MakeitMin(N, K, A, B));
    }
}
 
// This code is contributed by Rohit Pradhan


Python3




# Python code to implement the approach
 
# Function to calculate the maximum operations
def MakeitMin(n, k, a, b):
 
    # Create a vector pair to store the difference
    v = [[] for i in range(n)]
    for i in range(n):
        v[i] = [a[i] - b[i], a[i]]
 
    # Sort it accordingly
    v.sort()
    ans = 0
    for i in range(n):
 
        # Check if we can perform that turn or not
        if (v[i][1] > k):
            continue
 
        # If we can perform, calculate max times
        # we can perform that turn
        # and add it to ans
        diff = (k - (v[i][1] - v[i][0])) // v[i][0]
        ans += diff
 
        # Reduce the k value
        k -= (diff * v[i][0])
         
    return ans
 
 
# Driver Code
N,K = 2,10
A = [5, 4]
B = [1, 2]
print(MakeitMin(N, K, A, B))
 
# This code is contributed by shinjanpatra


C#




// C# code to implement the approach
using System;
using System.Collections.Generic;
 
public class GFG
{
   
    // Function to calculate the maximum operations
    public static int MakeitMin(int n, int k, int[] a,
                                int[] b)
    {
       
        // Create a array of pairs to store the difference
        int[][] v = new int[n][];
        for (int i = 0; i < n; i++) {
            v[i] = new int[] { a[i] - b[i], a[i] };
        }
 
        // Sort it accordingly
        Array.Sort(v, (x, y) => { return x[0] - y[0]; });
 
        int ans = 0;
        for (int i = 0; i < n; i++) {
 
            // Check if we can perform that turn or not
            if (v[i][1] > k)
                continue;
 
            // If we can perform, calculate max times
            // we can perform that turn
            // and add it to ans
            int diff = (k - (v[i][1] - v[i][0])) / v[i][0];
            ans += diff;
 
            // Reduce the k value
            k -= (diff * v[i][0]);
        }
        return ans;
    }
   
      // Driver Code
    public static void Main(string[] args)
    {
        int N = 2, K = 10;
        int[] A = { 5, 4 };
        int[] B = { 1, 2 };
       
          // Function Call
        Console.WriteLine(MakeitMin(N, K, A, B));
    }
}
 
// This code is contributed by phasing17.


Javascript




<script>
    // JavaScript code to implement the approach
     
    // Function to calculate the maximum operations
    const MakeitMin = (n, k, a, b) => {
     
        // Create a vector pair to store the difference
        let v = new Array(n).fill([]);
        for (let i = 0; i < n; i++)
            v[i] = [a[i] - b[i], a[i]];
 
        // Sort it accordingly
        v.sort();
        let ans = 0;
        for (let i = 0; i < n; i++) {
 
            // Check if we can perform that turn or not
            if (v[i][1] > k)
                continue;
 
            // If we can perform, calculate max times
            // we can perform that turn
            // and add it to ans
            let diff
                = (k - (v[i][1] - v[i][0])) / v[i][0];
            ans += diff;
 
            // Reduce the k value
            k -= (diff * v[i][0]);
        }
        return ans;
    }
 
    // Driver Code
    let N = 2, K = 10;
    let A = [5, 4];
    let B = [1, 2];
    document.write(MakeitMin(N, K, A, B));
 
// This code is contributed by rakeshsahni
 
</script>


Output

4

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

Another Approach:

  1. Create a vector of pairs to store the difference (A[i] – B[i]) and the value of A[i] for each index i in the arrays A[] and B[].
  2. Sort the vector of pairs in non-decreasing order of the difference (A[i] – B[i]). This will ensure that we always pick the indices with minimum difference (A[i] – B[i]) first.
  3. Initialize a variable ans to 0 to keep track of the maximum number of times we can perform the operation (K – A[i] + B[i]).
  4. Loop through the vector of pairs from the beginning to the end.
  5. Check if the value of A[i] is greater than K. If yes, continue to the next iteration of the loop, as we cannot perform the operation (K – A[i] + B[i]) for this index i.
  6. If the value of A[i] is less than or equal to K, calculate the maximum number of times we can perform the operation for this index i. We can do this by dividing (K – (A[i] – B[i])) by (A[i] – B[i]), and taking the floor of the result.
  7. Add the maximum number of times we can perform the operation for this index i to the variable ans.
  8. Reduce the value of K by the maximum number of times we can perform the operation for this index i, multiplied by (A[i] – B[i]).
  9. Repeat steps 5-8 until we have looped through all the indices in the vector of pairs.
  10. Return the value of ans as the final answer.

Below is the implementation of above approach:

C++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to calculate the maximum operations
int MakeitMin(int n, int k, int a[], int b[]) {
// Create a priority queue to store the indices with (A[i]-B[i])
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
for (int i = 0; i < n; i++) {
pq.push({a[i]-b[i], i});
}
   
  int ans = 0;
while (!pq.empty() && k >= 0) {
    int idx = pq.top().second;
    pq.pop();
     
    // Calculate the maximum number of operations for this index
    int max_ops = (k - (a[idx] - b[idx])) / (a[idx] - b[idx]);
     
    // Update the answer and the remaining value of K
    ans += max_ops;
    k -= max_ops * (a[idx] - b[idx]);
     
    // Push the index back into the priority queue if K is not negative
    if (max_ops > 0 && k >= 0) {
        pq.push({a[idx]-b[idx], idx});
    }
}
return ans;
}
// Driver Code
int main()
{
    int N = 2, K = 10;
    int A[] = { 5, 4 };
    int B[] = { 1, 2 };
    cout << MakeitMin(N, K, A, B);
    return 0;
}
  


Java




import java.util.Comparator;
import java.util.PriorityQueue;
 
class GFG
{
   
  // Function to calculate the maximum operations
  public static int makeItMin(int n, int k, int[] a, int[] b)
  {
     
    // Create a priority queue to store the indices with (A[i]-B[i])
    PriorityQueue<Pair<Integer, Integer>> pq =
      new PriorityQueue<>(Comparator.comparingInt(Pair::getKey));
    for (int i = 0; i < n; i++) {
      pq.offer(new Pair<>(a[i] - b[i], i));
    }
 
    int ans = 0;
    while (!pq.isEmpty() && k >= 0) {
      Pair<Integer, Integer> item = pq.poll();
      int idx = item.getValue();
 
      // Calculate the maximum number of operations for this index
      int max_ops = (k - (a[idx] - b[idx])) / (a[idx] - b[idx]);
 
      // Update the answer and the remaining value of K
      ans += max_ops;
      k -= max_ops * (a[idx] - b[idx]);
 
      // Push the index back into the priority queue if K is not negative
      if (max_ops > 0 && k >= 0) {
        pq.offer(new Pair<>(a[idx] - b[idx], idx));
      }
    }
    return ans;
  }
 
  // Driver Code
  public static void main(String[] args) {
    int N = 2, K = 10;
    int[] A = {5, 4};
    int[] B = {1, 2};
    System.out.println(makeItMin(N, K, A, B));
  }
 
  // Pair class definition
  static class Pair<K, V> {
    private final K key;
    private final V value;
 
    // Constructor
    public Pair(K key, V value) {
      this.key = key;
      this.value = value;
    }
 
    // Getters
    public K getKey() {
      return key;
    }
 
    public V getValue() {
      return value;
    }
  }
}


Python3




# Python3 code to implement the approach
import heapq
 
# Function to calculate the maximum operations
def MakeitMin(n, k, a, b):
   
    # Create a priority queue to store the indices with (A[i]-B[i])
    pq = []
    for i in range(n):
        heapq.heappush(pq, (a[i]-b[i], i))
   
    ans = 0
    while pq and k >= 0:
        idx = heapq.heappop(pq)[1]
         
        # Calculate the maximum number of operations for this index
        max_ops = int((k - (a[idx] - b[idx])) / (a[idx] - b[idx]))
         
        # Update the answer and the remaining value of K
        ans += max_ops
        k -= max_ops * (a[idx] - b[idx])
         
        # Push the index back into the priority queue if K is not negative
        if max_ops > 0 and k >= 0:
            heapq.heappush(pq, (a[idx]-b[idx], idx))
    return ans
 
# Driver Code
if __name__ == '__main__':
    N = 2
    K = 10
    A = [5, 4]
    B = [1, 2]
    print(MakeitMin(N, K, A, B))


C#




using System;
using System.Collections.Generic;
 
public class Program
{
    // Function to calculate the maximum operations
    public static int MakeitMin(int n, int k, int[] a, int[] b)
    {
        // Create a priority queue to store the indices with (A[i]-B[i])
        var pq = new PriorityQueue<(int, int)>((x, y) => x.Item1.CompareTo(y.Item1));
        for (int i = 0; i < n; i++)
        {
            pq.Enqueue((a[i] - b[i], i));
        }
 
        int ans = 0;
        while (pq.Count > 0 && k >= 0)
        {
            var item = pq.Dequeue();
            int idx = item.Item2;
 
            // Calculate the maximum number of operations for this index
            int max_ops = (k - (a[idx] - b[idx])) / (a[idx] - b[idx]);
 
            // Update the answer and the remaining value of K
            ans += max_ops;
            k -= max_ops * (a[idx] - b[idx]);
 
            // Push the index back into the priority queue if K is not negative
            if (max_ops > 0 && k >= 0)
            {
                pq.Enqueue((a[idx] - b[idx], idx));
            }
        }
        return ans;
    }
 
    // Driver Code
    public static void Main()
    {
        int N = 2, K = 10;
        int[] A = { 5, 4 };
        int[] B = { 1, 2 };
        Console.WriteLine(MakeitMin(N, K, A, B));
    }
}
 
// Implementation of priority queue in C#
public class PriorityQueue<T>
{
    private readonly List<T> _data;
    private readonly Comparison<T> _comparer;
 
    public PriorityQueue() : this(null) { }
    public PriorityQueue(Comparison<T> comparer)
    {
        _data = new List<T>();
        _comparer = comparer ?? Comparer<T>.Default.Compare;
    }
 
    public void Enqueue(T item)
    {
        _data.Add(item);
        int ci = _data.Count - 1;
        while (ci > 0)
        {
            int pi = (ci - 1) / 2;
            if (_comparer(_data[ci], _data[pi]) >= 0) break;
            T tmp = _data[ci]; _data[ci] = _data[pi]; _data[pi] = tmp;
            ci = pi;
        }
    }
 
    public T Dequeue()
    {
        int li = _data.Count - 1;
        T frontItem = _data[0];
        _data[0] = _data[li];
        _data.RemoveAt(li);
 
        --li;
        int ci = 0;
        while (true)
        {
            int rc = ci * 2 + 2;
            int lc = ci * 2 + 1;
            if (lc > li) break;
            int minc = (rc > li || _comparer(_data[lc], _data[rc]) < 0) ? lc : rc;
            if (_comparer(_data[ci], _data[minc]) <= 0) break;
            T tmp = _data[ci]; _data[ci] = _data[minc]; _data[minc] = tmp;
            ci = minc;
        }
        return frontItem;
    }
 
    public int Count { get { return _data.Count; } }
}


Javascript




// Function to calculate the maximum operations
function MakeitMin(n, k, a, b) {
  // Create an array to store the indices with (A[i]-B[i])
  const arr = [];
  for (let i = 0; i < n; i++) {
    arr.push([a[i] - b[i], i]);
  }
  // sort the array in descending order of diff
  arr.sort((a, b) => ((b[0] == a[0]) ? b[1] - a[1] : b[0] - a[0]));
 
  let ans = 0;
  while (arr.length && k >= 0) {
    const [diff, idx] = arr.pop(); // get the index with maximum diff
         
    // Calculate the maximum number of operations for this index
    const max_ops = Math.ceil((k - (a[idx] - b[idx])) / (a[idx] - b[idx]));
         
    // Update the answer and the remaining value of K
    ans += max_ops;
    k -= max_ops * (a[idx] - b[idx]);
         
    // Push the index back into the array if K is not negative
    if (max_ops > 0 && k >= 0) {
      arr.push([a[idx]-b[idx], idx]);
       // sort the array again after adding an element
      arr.sort((a, b) => ((b[0] == a[0]) ? b[1] - a[1] : b[0] - a[0]));
    }
  }
  return ans;
}
 
// Driver Code
  const N = 2;
  const K = 10;
  const A = [5, 4];
  const B = [1, 2];
  console.log(MakeitMin(N, K, A, B));


Output

4

Time Complexity: O(N*logN)

Auxiliary Space: O(N)



Last Updated : 19 Apr, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads