给定一个由整数组成的数组“ arr”,任务是找到非空子集,使其总和最接近零,即零和之和之间的绝对差最小。
例子:
Input : arr[] = {2, 2, 2, -4}
Output : 0
arr[0] + arr[1] + arr[3] = 0
That’s why answer is zero.
Input : arr[] = {1, 1, 1, 1}
Output : 1
一种简单的方法是递归生成所有可能的子集,并找到总和最接近零的子集。这种方法的时间复杂度将是O(2 ^ n)。
一种更好的方法是在伪多项式时间复杂度中使用动态规划。
让我们假设直到索引i-1为止我们选择的所有元素的总和是S。因此,从索引“ i”开始,我们必须找到一个总和最接近-S的子集。
首先定义dp [i] [S]。这意味着数组“ arr”的子数组{i,N-1}的子集的总和最接近“ -S”。
现在,我们可以在当前总和中包括“ i”或保留它。因此,我们有两种可能的方法。如果我们包含“ i”,则当前总和将更新为S + arr [i],我们将求解索引“ i + 1”,即dp [i + 1] [S + arr [i]],否则我们将求解直接索引“ i + 1”。因此,所需的递归关系将是。
dp[i][s] = RetClose(arr[i]+dp[i][s+arr[i]], dp[i+1][s], -s);
where RetClose(a, b, c) returns a if |a-c|<|b-c| else it returns b
下面是上述方法的实现:
C++
#include
using namespace std;
#define arrSize 51
#define maxSum 201
#define MAX 100
#define inf 999999
// Variable to store states of dp
int dp[arrSize][maxSum];
bool visit[arrSize][maxSum];
// Function to return the number closer to integer s
int RetClose(int a, int b, int s)
{
if (abs(a - s) < abs(b - s))
return a;
else
return b;
}
// To find the sum closest to zero
// Since sum can be negative, we will add MAX
// to it to make it positive
int MinDiff(int i, int sum, int arr[], int n)
{
// Base cases
if (i == n)
return 0;
// Checks if a state is already solved
if (visit[i][sum + MAX])
return dp[i][sum + MAX];
visit[i][sum + MAX] = 1;
// Recurrence relation
dp[i][sum + MAX] = RetClose(arr[i] +
MinDiff(i + 1, sum + arr[i], arr, n),
MinDiff(i + 1, sum, arr, n), -1 * sum);
// Returning the value
return dp[i][sum + MAX];
}
// Function to calculate the closest sum value
void FindClose(int arr[],int n)
{
int ans=inf;
// Calculate the Closest value for every
// subarray arr[i-1:n]
for (int i = 1; i <= n; i++)
ans = RetClose(arr[i - 1] +
MinDiff(i, arr[i - 1], arr, n), ans, 0);
cout<
Java
// Java Program for above approach
import java.io.*;
class GFG
{
static int arrSize = 51;
static int maxSum = 201;
static int MAX = 100;
static int inf = 999999;
// Variable to store states of dp
static int dp[][] = new int [arrSize][maxSum];
static int visit[][] = new int [arrSize][maxSum];
// Function to return the number
// closer to integer s
static int RetClose(int a, int b, int s)
{
if (Math.abs(a - s) < Math.abs(b - s))
return a;
else
return b;
}
// To find the sum closest to zero
// Since sum can be negative, we will add MAX
// to it to make it positive
static int MinDiff(int i, int sum,
int arr[], int n)
{
// Base cases
if (i == n)
return 0;
// Checks if a state is already solved
if (visit[i][sum + MAX] > 0 )
return dp[i][sum + MAX];
visit[i][sum + MAX] = 1;
// Recurrence relation
dp[i][sum + MAX] = RetClose(arr[i] +
MinDiff(i + 1, sum + arr[i], arr, n),
MinDiff(i + 1, sum, arr, n), -1 * sum);
// Returning the value
return dp[i][sum + MAX];
}
// Function to calculate the closest sum value
static void FindClose(int arr[], int n)
{
int ans = inf;
// Calculate the Closest value for every
// subarray arr[i-1:n]
for (int i = 1; i <= n; i++)
ans = RetClose(arr[i - 1] +
MinDiff(i, arr[i - 1],
arr, n), ans, 0);
System.out.println(ans);
}
// Driver Code
public static void main (String[] args)
{
// Input array
int arr[] = { 25, -9, -10, -4, -7, -33 };
int n = arr.length;
FindClose(arr,n);
}
}
// This code is contributed by ajit_00023@
Python3
# Python3 Code for above implementation
import numpy as np
arrSize = 51
maxSum = 201
MAX = 100
inf = 999999
# Variable to store states of dp
dp = np.zeros((arrSize,maxSum));
visit = np.zeros((arrSize,maxSum));
# Function to return the number closer to integer s
def RetClose(a, b, s) :
if (abs(a - s) < abs(b - s)) :
return a;
else :
return b;
# To find the sum closest to zero
# Since sum can be negative, we will add MAX
# to it to make it positive
def MinDiff(i, sum, arr, n) :
# Base cases
if (i == n) :
return 0;
# Checks if a state is already solved
if (visit[i][sum + MAX]) :
return dp[i][sum + MAX];
visit[i][sum + MAX] = 1;
# Recurrence relation
dp[i][sum + MAX] = RetClose(arr[i] +
MinDiff(i + 1, sum + arr[i], arr, n),
MinDiff(i + 1, sum, arr, n), -1 * sum);
# Returning the value
return dp[i][sum + MAX];
# Function to calculate the closest sum value
def FindClose(arr,n) :
ans=inf;
# Calculate the Closest value for every
# subarray arr[i-1:n]
for i in range(1, n + 1) :
ans = RetClose(arr[i - 1] +
MinDiff(i, arr[i - 1], arr, n), ans, 0);
print(ans);
# Driver function
if __name__ == "__main__" :
# Input array
arr = [ 25, -9, -10, -4, -7, -33 ];
n = len(arr);
FindClose(arr,n);
# This code is contributed by AnkitRai01
C#
// C# Program for above approach
using System;
class GFG
{
static int arrSize = 51;
static int maxSum = 201;
static int MAX = 100;
static int inf = 999999;
// Variable to store states of dp
static int [,]dp = new int [arrSize,maxSum];
static int [,]visit = new int [arrSize,maxSum];
// Function to return the number
// closer to integer s
static int RetClose(int a, int b, int s)
{
if (Math.Abs(a - s) < Math.Abs(b - s))
return a;
else
return b;
}
// To find the sum closest to zero
// Since sum can be negative, we will add MAX
// to it to make it positive
static int MinDiff(int i, int sum,
int []arr, int n)
{
// Base cases
if (i == n)
return 0;
// Checks if a state is already solved
if (visit[i,sum + MAX] > 0 )
return dp[i,sum + MAX];
visit[i,sum + MAX] = 1;
// Recurrence relation
dp[i,sum + MAX] = RetClose(arr[i] +
MinDiff(i + 1, sum + arr[i], arr, n),
MinDiff(i + 1, sum, arr, n), -1 * sum);
// Returning the value
return dp[i,sum + MAX];
}
// Function to calculate the closest sum value
static void FindClose(int []arr, int n)
{
int ans = inf;
// Calculate the Closest value for every
// subarray arr[i-1:n]
for (int i = 1; i <= n; i++)
ans = RetClose(arr[i - 1] +
MinDiff(i, arr[i - 1],
arr, n), ans, 0);
Console.WriteLine(ans);
}
// Driver Code
public static void Main ()
{
// Input array
int []arr = { 25, -9, -10, -4, -7, -33 };
int n = arr.Length;
FindClose(arr,n);
}
}
// This code is contributed by anuj_67..
-1
时间复杂度:O(N * S),其中N是数组中元素的数量,S是数组中所有数字的总和。