使给定数组中最多 S 的数组求和的最小操作
给定一个大小为N的数组arr[]和一个整数S ,任务是找到使数组之和小于或等于S的最小操作。在每个操作中:
- 可以选择任何元素,并且可以减 1,或者
- 可以被数组中的任何其他元素替换。
例子:
Input: arr[]= {1, 2, 1 ,3, 1 ,2, 1}, S= 8
Output: 2
Explanation: Initially sum of the array is 11.
Now decrease 1 at index 0 to 0 and Replace 3 by 0.
The sum becomes 7 < 8. So 2 operations.
Input: arr[] = {1,2,3,4}, S= 11
Output: 0
Explanation: Sum is already < =11 so 0 operations.
方法:这个问题可以使用贪心方法和通过对数组排序的后缀求和来解决。对最小元素应用第一个操作任意次数,然后通过在第一个操作后将其替换为最小元素来对后缀应用第二个操作给出最小操作。
First sort the array. Consider performing x operations of 1st type on the arr[0] and then performing the 2nd operation on the suffix of the array of length i. Also consider the sum for this suffix of length i is sufSum.
Sum of the modified array must be <=S
So, the difference to be subtracted from the sum must be (diff)>= sum – S.
If x operations of type 1 is done on minimum element and type 2 operations are done the suffix of the array from [i,n) the sum of the decreased array is
cost = x + s – (n-i) * (a[0] – x)
cost = (n-i+1)* x-(n-i)* a[0] +s
cost >= sum – S = diff
s – (n-i) * a[0] + (n-i+1) *x >= diff
so x >= (diff – s+(n-i)* a[0]) / (n-i+1)
The minimum value of x is x = ceil((diff -s+ (n-i)* a[0]) / (n-i+1))
So the total operations are x (type-1) + (n-i) type-2
按照以下步骤解决上述问题:
- 将变量sum = 0和数组的大小初始化为N 。
- 遍历向量并找到数组的总和。
- 如果sum < = S打印 0 并返回。
- 对向量进行排序并分配diff = sum-S 。
- 初始化ops = sum-S ,这是最大可能的操作。
- 初始化s =0存储向量的后缀和。
- 现在使用 for 循环从向量的末尾遍历。
- 跟踪s变量中的后缀总和。
- 初始化一个dec变量,该变量是要从数组的后缀递减的值
- 如果s-dec大于或等于diff ,则无需递减arr[0] ,因此分配x =0 。
- 否则找到x的值,它是arr[0]中要递减的值,并找到最小操作。
- 打印最少的操作
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to divide and get the ceil value
int ceil_div(int a, int b)
{
return a / b + ((a ^ b) > 0 && a % b);
}
// Function to find the minimum cost
void minimum_cost(vector arr, int S)
{
int sum = 0;
int n = arr.size();
// Find the sum of the array
for (int i = 0; i < arr.size(); i++) {
sum += arr[i];
}
// If sum <= S no operations required
if (sum <= S) {
cout << 0 << endl;
return;
}
// Sort the array
sort(arr.begin(), arr.end());
int diff = sum - S;
// Maximum it requires sum-S operations
// by decrementing
// the arr[0] by 1
int ops = sum - S;
// suffix sum
int s = 0;
int x;
for (int i = n - 1; i > 0; i--) {
s += arr[i];
// If replacing the last elements
// with doing the first operation
// x = 0 Decrementing the a[i] from
// the suffix [i,n-1]
int dec = (n - i) * arr[0];
if (s - dec >= diff) {
x = 0;
}
// Find how times the first element
// should be decremented by 1 and
// incremented by 1 which is x
else {
x = max(ceil_div((diff - s + dec),
(n - i + 1)), 0);
}
// First operation + second operation
if (x + n - i < ops) {
ops = x + n - i;
}
}
// Print the operations
cout << ops << endl;
}
// Driver code
int main()
{
// Initialize the array
vector arr = { 1, 2, 1, 3, 1, 2, 1 };
int S = 8;
// Function call
minimum_cost(arr, S);
return 0;
}
Java
// Java program for the above approach
import java.util.Arrays;
class GFG {
// Function to divide and get the ceil value
static int ceil_div(int a, int b) {
int temp = 0;
if (((a ^ b) > 0) && ((a % b) > 0)) {
temp = 1;
}
return (a / b) + temp;
}
// Function to find the minimum cost
static void minimum_cost(int[] arr, int S) {
int sum = 0;
int n = arr.length;
// Find the sum of the array
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
// If sum <= S no operations required
if (sum <= S) {
System.out.println(0);
return;
}
// Sort the array
Arrays.sort(arr);
int diff = sum - S;
// Maximum it requires sum-S operations
// by decrementing
// the arr[0] by 1
int ops = sum - S;
// suffix sum
int s = 0;
int x;
for (int i = n - 1; i > 0; i--) {
s += arr[i];
// If replacing the last elements
// with doing the first operation
// x = 0 Decrementing the a[i] from
// the suffix [i,n-1]
int dec = (n - i) * arr[0];
if (s - dec >= diff) {
x = 0;
}
// Find how times the first element
// should be decremented by 1 and
// incremented by 1 which is x
else {
x = Math.max(ceil_div((diff - s + dec),
(n - i + 1)), 0);
}
// First operation + second operation
if (x + n - i < ops) {
ops = x + n - i;
}
}
// Print the operations
System.out.println(ops);
}
// Driver code
public static void main(String args[])
{
// Initialize the array
int[] arr = { 1, 2, 1, 3, 1, 2, 1 };
int S = 8;
// Function call
minimum_cost(arr, S);
}
}
// This code is contributed by saurabh_jaiswal.
Python3
# Python 3 program for the above approach
# Function to divide and get the ceil value
def ceil_div(a, b):
return a // b + ((a ^ b) > 0 and a % b)
# Function to find the minimum cost
def minimum_cost(arr, S):
sum = 0
n = len(arr)
# Find the sum of the array
for i in range(len(arr)):
sum += arr[i]
# If sum <= S no operations required
if (sum <= S):
print(0)
return
# Sort the array
arr.sort()
diff = sum - S
# Maximum it requires sum-S operations
# by decrementing
# the arr[0] by 1
ops = sum - S
# suffix sum
s = 0
for i in range(n - 1, -1, -1):
s += arr[i]
# If replacing the last elements
# with doing the first operation
# x = 0 Decrementing the a[i] from
# the suffix [i,n-1]
dec = (n - i) * arr[0]
if (s - dec >= diff):
x = 0
# Find how times the first element
# should be decremented by 1 and
# incremented by 1 which is x
else:
x = max(ceil_div((diff - s + dec),
(n - i + 1)), 0)
# First operation + second operation
if (x + n - i < ops):
ops = x + n - i
# Print the operations
print(ops)
# Driver code
if __name__ == "__main__":
# Initialize the array
arr = [1, 2, 1, 3, 1, 2, 1]
S = 8
# Function call
minimum_cost(arr, S)
# This code is contributed by ukasp.
C#
// C# program for the above approach
using System;
class GFG
{
// Function to divide and get the ceil value
static int ceil_div(int a, int b) {
int temp = 0;
if (((a ^ b) > 0) && ((a % b) > 0)) {
temp = 1;
}
return (a / b) + temp;
}
// Function to find the minimum cost
static void minimum_cost(int[] arr, int S) {
int sum = 0;
int n = arr.Length;
// Find the sum of the array
for (int i = 0; i < arr.Length; i++) {
sum += arr[i];
}
// If sum <= S no operations required
if (sum <= S) {
Console.WriteLine(0);
return;
}
// Sort the array
Array.Sort(arr);
int diff = sum - S;
// Maximum it requires sum-S operations
// by decrementing
// the arr[0] by 1
int ops = sum - S;
// suffix sum
int s = 0;
int x;
for (int i = n - 1; i > 0; i--) {
s += arr[i];
// If replacing the last elements
// with doing the first operation
// x = 0 Decrementing the a[i] from
// the suffix [i,n-1]
int dec = (n - i) * arr[0];
if (s - dec >= diff) {
x = 0;
}
// Find how times the first element
// should be decremented by 1 and
// incremented by 1 which is x
else {
x = Math.Max(ceil_div((diff - s + dec),
(n - i + 1)), 0);
}
// First operation + second operation
if (x + n - i < ops) {
ops = x + n - i;
}
}
// Print the operations
Console.Write(ops);
}
// Driver code
public static void Main()
{
// Initialize the array
int[] arr = { 1, 2, 1, 3, 1, 2, 1 };
int S = 8;
// Function call
minimum_cost(arr, S);
}
}
// This code is contributed by Samim Hossain Mondal.
Javascript
2
时间复杂度: O(N* logN)
空间复杂度: O(1)