给定一个由整数组成的数组“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)。
更好的方法是在Pseudo Polynomial Time Complexity 中使用动态编程。
让我们假设我们选择的所有元素的总和直到索引 ‘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..
Javascript
-1
时间复杂度:O(N*S),其中 N 是数组中元素的数量,S 是数组中所有数字的总和。
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。