📌  相关文章
📜  最小化 Array 中的变化总和,使得新元素与数组总和的比率最多为 p:q

📅  最后修改于: 2022-05-13 01:56:08.974000             🧑  作者: Mango

最小化 Array 中的变化总和,使得新元素与数组总和的比率最多为 p:q

给定一个包含n 个整数和两个整数pq的数组A ,任务是增加数组 A中的一些(或全部)值,使得每个元素(在第一个元素之后)相对于总和的比率当前元素之前的所有元素的值仍然小于或等于p / q 。返回要完成的最小更改总和。

例子:

方法:使用前缀和和二进制搜索的概念可以很容易地解决这个问题。

请按照以下步骤解决问题 -

  • 制作给定数组的前缀和数组。
  • 在 0 到 INT_MAX 范围内使用二进制搜索找到可能的最小答案。

下面是上述方法的实现:

C++
// C++ program for find minimum
// sum of changes in an array
#include 
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.


Python3
# 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



输出
99

时间复杂度:O(n log(INT_MAX))
辅助空间:O(n)