Minimize sum of changes in Array such that ratio of new element to array sum is at most p:q
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
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++
#include <bits/stdc++.h>
using namespace std;
bool isValid( int candidate, int pre[], int n, int A[],
int p, int q)
{
bool flag = true ;
for ( int i = 1; i < n; i++) {
int curr_sum = pre[i - 1] + candidate;
if (A[i] * q > p * curr_sum) {
flag = false ;
break ;
}
}
return flag;
}
int solve( int n, int A[], int p, int q)
{
int pre[n];
pre[0] = A[0];
for ( int i = 1; i < n; i++) {
pre[i] = A[i] + pre[i - 1];
}
int lo = 0, hi = INT_MAX, ans = INT_MAX;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (isValid(mid, pre, n, A, p, q)) {
ans = mid;
hi = mid - 1;
}
else {
lo = mid + 1;
}
}
return ans;
}
int main()
{
int n, p, q;
n = 4, p = 1, q = 100;
int A[] = { 20100, 1, 202, 202 };
cout << solve(n, A, p, q) << endl;
}
|
Java
import java.io.*;
class GFG {
static Boolean isValid( int candidate, int pre[], int n, int A[],
int p, int q)
{
Boolean flag = true ;
for ( int i = 1 ; i < n; i++) {
int curr_sum = pre[i - 1 ] + candidate;
if (A[i] * q > p * curr_sum) {
flag = false ;
break ;
}
}
return flag;
}
static int solve( int n, int A[], int p, int q)
{
int pre[] = new int [n];
pre[ 0 ] = A[ 0 ];
for ( int i = 1 ; i < n; i++) {
pre[i] = A[i] + pre[i - 1 ];
}
int lo = 0 , hi = Integer.MAX_VALUE, ans = Integer.MAX_VALUE;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2 ;
if (isValid(mid, pre, n, A, p, q)) {
ans = mid;
hi = mid - 1 ;
}
else {
lo = mid + 1 ;
}
}
return ans;
}
public static void main (String[] args)
{
int n = 4 , p = 1 , q = 100 ;
int A[] = { 20100 , 1 , 202 , 202 };
System.out.println(solve(n, A, p, q));
}
}
|
Python3
import sys
def isValid(candidate, pre, n, A, p, q) :
flag = True
for i in range ( 1 , n) :
curr_sum = pre[i - 1 ] + candidate
if (A[i] * q > p * curr_sum) :
flag = False
break
return flag
def solve(n, A, p, q) :
pre = [ 0 ] * 100
pre[ 0 ] = A[ 0 ]
for i in range ( 1 , n) :
pre[i] = A[i] + pre[i - 1 ]
lo = 0
hi = sys.maxsize
ans = sys.maxsize
while (lo < = hi) :
mid = lo + (hi - lo) / / 2
if (isValid(mid, pre, n, A, p, q)) :
ans = mid
hi = mid - 1
else :
lo = mid + 1
return ans
n = 4
p = 1
q = 100
A = [ 20100 , 1 , 202 , 202 ]
print (solve(n, A, p, q))
|
C#
using System;
class GFG
{
static bool isValid( int candidate, int []pre, int n, int []A,
int p, int q)
{
bool flag = true ;
for ( int i = 1; i < n; i++) {
int curr_sum = pre[i - 1] + candidate;
if (A[i] * q > p * curr_sum) {
flag = false ;
break ;
}
}
return flag;
}
static int solve( int n, int []A, int p, int q)
{
int []pre = new int [n];
pre[0] = A[0];
for ( int i = 1; i < n; i++) {
pre[i] = A[i] + pre[i - 1];
}
int lo = 0, hi = Int32.MaxValue, ans = Int32.MaxValue;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (isValid(mid, pre, n, A, p, q)) {
ans = mid;
hi = mid - 1;
}
else {
lo = mid + 1;
}
}
return ans;
}
public static void Main()
{
int n = 4, p = 1, q = 100;
int []A = { 20100, 1, 202, 202 };
Console.WriteLine(solve(n, A, p, q));
}
}
|
Javascript
<script>
const INT_MAX = 2147483647;
const isValid = (candidate, pre, n, A, p, q) => {
let flag = true ;
for (let i = 1; i < n; i++) {
let curr_sum = pre[i - 1] + candidate;
if (A[i] * q > p * curr_sum) {
flag = false ;
break ;
}
}
return flag;
}
let solve = (n, A, p, q) => {
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];
}
let lo = 0, hi = INT_MAX, ans = INT_MAX;
while (lo <= hi) {
let mid = lo + parseInt((hi - lo) / 2);
if (isValid(mid, pre, n, A, p, q)) {
ans = mid;
hi = mid - 1;
}
else {
lo = mid + 1;
}
}
return ans;
}
let n, p, q;
n = 4, p = 1, q = 100;
let A = [20100, 1, 202, 202];
document.write(solve(n, A, p, q));
</script>
|
Time Complexity: O(n log(INT_MAX))
Auxiliary space: O(n)
Last Updated :
29 Mar, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...