Minimize sum of changes in Array such that ratio of new element to array sum is at most p:q
Last Updated :
06 Dec, 2024
Given an array A of n integers and two integers p and q, the task is to increase some (or all) of the values in array A in such a way that ratio of each element (after first element) with respect to the total sum of all elements before the current element remains less than or equal to p/q. Return the minimum sum of changes to be done.
Examples:
Input: n = 4, A = {20100, 1, 202, 202}, p = 1, q = 100
Output: 99
Explanation: 50 is added to the first element and 49 to the second element, so that the resulting array becomes {20150, 50, 202, 202}.
50/20150 <= 1/100
202/(20150+50) <=1/100
202/(20150+50+202)<=1/100
Therefore, the condition is satisfied for all the elements and hence 50+49=99 would be the answer.
There are other answers possible as well, but we need to find out the minimum possible sum.
Input: n = 3, A = {1, 1, 1}, p = 100, q = 100
Output: 0
Learn About : Ratio and Proportions
Approach: The problem can be easily solved using the concepts of prefix sum and binary search.
- It can be clearly observed that
- if the condition stated in the problem is achieved for a certain sum of changes (say S),
- then it is always possible to achieve the condition for all the numbers greater than S and
- cannot be achieved for all numbers less than S.
- So, we can apply binary search to find the answer.
- Also, it must be carefully observed that instead of distributing S(sum of changes) over different elements, if we just add it to first element, that would not affect the answer.
For example, in the first example above, if 99 is added to the first element, the resultant array will still meet the required condition.
Follow the steps below to solve the problem -
- Make a prefix sum array of the given array.
- Using binary search on range 0 to INT_MAX find the minimum possible answer.
NOTE: Division may lead to overlapping values and errors.
So, instead of comparison like (a/b)<=(c/d), we will do (a*d)<=(b*c).
Below is the implementation of the above approach:
C++
// C++ program for find minimum
// sum of changes in an array
#include <bits/stdc++.h>
using namespace std;
// function to check if the candidate sum
// satisfies the condition of the problem
bool isValid(int candidate, int pre[], int n, int A[],
int p, int q)
{
// flag variable to check wrong answer
bool flag = true;
for (int i = 1; i < n; i++) {
// Now for each element, we are checking
// if its ratio with sum of all previous
// elements + candidate is greater than p/q.
// If so, we will return false.
int curr_sum = pre[i - 1] + candidate;
if (A[i] * q > p * curr_sum) {
flag = false;
break;
}
// comparing like A[i]/(curr_sum)>p/q
// will be error prone.
}
return flag;
}
int solve(int n, int A[], int p, int q)
{
// declaring and constructing
// prefix sum array
int pre[n];
pre[0] = A[0];
for (int i = 1; i < n; i++) {
pre[i] = A[i] + pre[i - 1];
}
// setting lower and upper bound for
// binary search
int lo = 0, hi = INT_MAX, ans = INT_MAX;
// since minimum answer is needed,
// so it is initialized with INT_MAX
while (lo <= hi) {
// calculating mid by using (lo+hi)/2
// may overflow in certain cases
int mid = lo + (hi - lo) / 2;
// checking if required ratio would be
// achieved by all elements if "mid" is
// considered as answer
if (isValid(mid, pre, n, A, p, q)) {
ans = mid;
hi = mid - 1;
}
else {
lo = mid + 1;
}
}
return ans;
}
// Driver Function
int main()
{
int n, p, q;
n = 4, p = 1, q = 100;
int A[] = { 20100, 1, 202, 202 };
// printing the required answer
cout << solve(n, A, p, q) << endl;
}
Java
// Java program for find minimum
// sum of changes in an arraykage whatever //do not write package name here */
import java.io.*;
class GFG {
// function to check if the candidate sum
// satisfies the condition of the problem
static Boolean isValid(int candidate, int pre[], int n, int A[],
int p, int q)
{
// flag variable to check wrong answer
Boolean flag = true;
for (int i = 1; i < n; i++) {
// Now for each element, we are checking
// if its ratio with sum of all previous
// elements + candidate is greater than p/q.
// If so, we will return false.
int curr_sum = pre[i - 1] + candidate;
if (A[i] * q > p * curr_sum) {
flag = false;
break;
}
// comparing like A[i]/(curr_sum)>p/q
// will be error prone.
}
return flag;
}
static int solve(int n, int A[], int p, int q)
{
// declaring and constructing
// prefix sum array
int pre[] = new int[n];
pre[0] = A[0];
for (int i = 1; i < n; i++) {
pre[i] = A[i] + pre[i - 1];
}
// setting lower and upper bound for
// binary search
int lo = 0, hi = Integer.MAX_VALUE, ans = Integer.MAX_VALUE;
// since minimum answer is needed,
// so it is initialized with INT_MAX
while (lo <= hi) {
// calculating mid by using (lo+hi)/2
// may overflow in certain cases
int mid = lo + (hi - lo) / 2;
// checking if required ratio would be
// achieved by all elements if "mid" is
// considered as answer
if (isValid(mid, pre, n, A, p, q)) {
ans = mid;
hi = mid - 1;
}
else {
lo = mid + 1;
}
}
return ans;
}
// Driver Function
public static void main (String[] args)
{
int n = 4, p = 1, q = 100;
int A[] = { 20100, 1, 202, 202 };
// printing the required answer
System.out.println(solve(n, A, p, q));
}
}
// This code is contributed by hrithikgarg03188.
Python
# Python code for the above approach
import sys
# function to check if the candidate sum
# satisfies the condition of the problem
def isValid(candidate, pre, n, A, p, q) :
# flag variable to check wrong answer
flag = True
for i in range(1, n) :
# Now for each element, we are checking
# if its ratio with sum of all previous
# elements + candidate is greater than p/q.
# If so, we will return false.
curr_sum = pre[i - 1] + candidate
if (A[i] * q > p * curr_sum) :
flag = False
break
# comparing like A[i]/(curr_sum)>p/q
# will be error prone.
return flag
def solve(n, A, p, q) :
# declaring and constructing
# prefix sum array
pre = [0] * 100
pre[0] = A[0]
for i in range(1, n) :
pre[i] = A[i] + pre[i - 1]
# setting lower and upper bound for
# binary search
lo = 0
hi = sys.maxsize
ans = sys.maxsize
# since minimum answer is needed,
# so it is initialized with INT_MAX
while (lo <= hi) :
# calculating mid by using (lo+hi)/2
# may overflow in certain cases
mid = lo + (hi - lo) // 2
# checking if required ratio would be
# achieved by all elements if "mid" is
# considered as answer
if (isValid(mid, pre, n, A, p, q)) :
ans = mid
hi = mid - 1
else :
lo = mid + 1
return ans
# Driver Function
n = 4
p = 1
q = 100
A = [ 20100, 1, 202, 202 ]
# printing the required answer
print(solve(n, A, p, q))
# This code is contributed by code_hunt.
C#
// C# program for find minimum
// sum of changes in an array
using System;
class GFG
{
// function to check if the candidate sum
// satisfies the condition of the problem
static bool isValid(int candidate, int []pre, int n, int []A,
int p, int q)
{
// flag variable to check wrong answer
bool flag = true;
for (int i = 1; i < n; i++) {
// Now for each element, we are checking
// if its ratio with sum of all previous
// elements + candidate is greater than p/q.
// If so, we will return false.
int curr_sum = pre[i - 1] + candidate;
if (A[i] * q > p * curr_sum) {
flag = false;
break;
}
// comparing like A[i]/(curr_sum)>p/q
// will be error prone.
}
return flag;
}
static int solve(int n, int []A, int p, int q)
{
// declaring and constructing
// prefix sum array
int []pre = new int[n];
pre[0] = A[0];
for (int i = 1; i < n; i++) {
pre[i] = A[i] + pre[i - 1];
}
// setting lower and upper bound for
// binary search
int lo = 0, hi = Int32.MaxValue, ans = Int32.MaxValue;
// since minimum answer is needed,
// so it is initialized with INT_MAX
while (lo <= hi) {
// calculating mid by using (lo+hi)/2
// may overflow in certain cases
int mid = lo + (hi - lo) / 2;
// checking if required ratio would be
// achieved by all elements if "mid" is
// considered as answer
if (isValid(mid, pre, n, A, p, q)) {
ans = mid;
hi = mid - 1;
}
else {
lo = mid + 1;
}
}
return ans;
}
// Driver Function
public static void Main()
{
int n = 4, p = 1, q = 100;
int []A = { 20100, 1, 202, 202 };
// printing the required answer
Console.WriteLine(solve(n, A, p, q));
}
}
// This code is contributed by Samim Hossain Mondal.
JavaScript
<script>
// JavaScript program for find minimum
// sum of changes in an array
const INT_MAX = 2147483647;
// function to check if the candidate sum
// satisfies the condition of the problem
const isValid = (candidate, pre, n, A, p, q) => {
// flag variable to check wrong answer
let flag = true;
for (let i = 1; i < n; i++) {
// Now for each element, we are checking
// if its ratio with sum of all previous
// elements + candidate is greater than p/q.
// If so, we will return false.
let curr_sum = pre[i - 1] + candidate;
if (A[i] * q > p * curr_sum) {
flag = false;
break;
}
// comparing like A[i]/(curr_sum)>p/q
// will be error prone.
}
return flag;
}
let solve = (n, A, p, q) => {
// declaring and constructing
// prefix sum array
let pre = new Array(n).fill(0);
pre[0] = A[0];
for (let i = 1; i < n; i++) {
pre[i] = A[i] + pre[i - 1];
}
// setting lower and upper bound for
// binary search
let lo = 0, hi = INT_MAX, ans = INT_MAX;
// since minimum answer is needed,
// so it is initialized with INT_MAX
while (lo <= hi) {
// calculating mid by using (lo+hi)/2
// may overflow in certain cases
let mid = lo + parseInt((hi - lo) / 2);
// checking if required ratio would be
// achieved by all elements if "mid" is
// considered as answer
if (isValid(mid, pre, n, A, p, q)) {
ans = mid;
hi = mid - 1;
}
else {
lo = mid + 1;
}
}
return ans;
}
// Driver Function
let n, p, q;
n = 4, p = 1, q = 100;
let A = [20100, 1, 202, 202];
// printing the required answer
document.write(solve(n, A, p, q));
// This code is contributed by rakeshsahni
</script>
Time Complexity: O(n log(INT_MAX))
Auxiliary space: O(n)
Similar Reads
Minimum operations to make Array sum at most S from given Array
Given an array arr[], of size N and an integer S, the task is to find the minimum operations to make the sum of the array less than or equal to S. In each operation: Any element can be chosen and can be decremented by 1, orCan be replaced by any other element in the array. Examples: Input: arr[]= {1
10 min read
Minimize sum of absolute differences of same-indexed elements of two given arrays by at most one replacement
Given two arrays A[] and B[] of size N each, the task is to find the minimum possible sum of absolute difference of same indexed elements of the two arrays, i.e. sum of |A[i] - B[i]| for all i such that 0 ? i < N by replacing at most one element in A[] with another element of A[]. Examples: Input
10 min read
Minimize removal from Array so that in any pair one element is multiple of other
Given an array arr[] of size N, the task is to count the minimum number of elements required to be removed from the given array such that whenever any pair (arr[i], arr[j]) is picked, where i != j and 0 ⤠i < j < N, either arr[i] is multiple of arr[j] or vice versa. Examples: Input: N = 5, arr
8 min read
Minimum number of changes such that elements are first Negative and then Positive
Given an array arr[] of size N. The task is to find the minimum number of changes required to convert the array such that for any index 0 ? k < N, the elements in the array upto k-th index will be less than zero and after k-th index will be greater than zero.That is: arr[0] < 0, arr[1] < 0,
7 min read
Minimum size of subset of pairs whose sum is at least the remaining array elements
Given two arrays A[] and B[] both consisting of N positive integers, the task is to find the minimum size of the subsets of pair of elements (A[i], B[i]) such that the sum of all the pairs of subsets is at least the sum of remaining array elements A[] which are not including in the subset i.e., (A[0
11 min read
Remove minimum elements from ends of array so that sum decreases by at least K | O(N)
Given an array arr[] consisting of N elements, the task is to remove minimum number of elements from the ends of the array such that the total sum of the array decreases by at least K. Note that K will always be less than or equal to the sum of all the elements of the array. Examples: Input: arr[] =
7 min read
Minimize modulo operations to make given Array a permutation of [1, N]
Given an array arr[] of size N, the task is to find the minimum number of operations required to make the array a permutation of numbers in range [1, N] where, in each operation, an element at any index i can be replaced by arr[i]%k (k = any value greater than 0). Return -1 if the array cannot be ma
7 min read
Find K such that sum of hamming distances between K and each Array element is minimised
Given an array arr[] of N non-negative integers and an integer P (1 ⤠P ⤠30), which denotes the upper limit of any number in the array to be (2P - 1). The task is to find a number such that the sum of Hamming distances between the number itself and all the numbers in the array is minimum. If there
12 min read
Minimum operations required to change the array such that |arr[i] - M| <= 1
Given an array arr[] of integers, the task is to find the minimum number of operations required to change the array elements such that for any positive integer M, |arr[i] - M| ? 1 for all valid i. In a single operation, any element of the array can either be incremented or decremented by 1.Examples:
6 min read
Minimize the non-zero elements in the Array by given operation
Given an array arr[] of length N, the task is to minimize the count of the number of non-zero elements by adding the value of the current element to any of its adjacent element and subtracting from the current element at most once.Examples: Input: arr[] = { 1, 0, 1, 0, 0, 1 } Output: 2 Explanation:
5 min read