给定一个包含N个元素的数组A。将此数组的任何子集划分为两个不相交的子集,以使两个子集具有相同的总和。获得分区后可获得的最大和。
注意:不必对整个数组进行分区,因为任何元素可能都不会对分区产生任何影响。
例子:
Input: A = [1, 2, 3, 6]
Output: 6
Explanation: We have two disjoint subsets {1, 2, 3} and {6}, which have the same sum = 6
Input: A = [1, 2, 3, 4, 5, 6]
Output: 10
Explanation: We have two disjoint subsets {2, 3, 5} and {4, 6}, which have the same sum = 10.
Input: A = [1, 2]
Output: 0
Explanation: No subset can be partitioned into 2 disjoint subsets with identical sum
天真的方法:
上述问题可以通过递归的蛮力法解决。所有元素都有三种可能性。它将有助于分区1或分区2,或者将不包含在任何分区中。我们将在每个元素上执行这三个操作,并在每个递归步骤中进行到下一个元素。
下面是上述方法的实现:
C++
// CPP implementation for the
// above mentioned recursive approach
#include
using namespace std;
// Function to find the maximum subset sum
int maxSum(int p0, int p1, int a[], int pos, int n)
{
if (pos == n) {
if (p0 == p1)
return p0;
else
return 0;
}
// Ignore the current element
int ans = maxSum(p0, p1, a, pos + 1, n);
// including element in partition 1
ans = max(ans, maxSum(p0 + a[pos], p1, a, pos + 1, n));
// including element in partition 2
ans = max(ans, maxSum(p0, p1 + a[pos], a, pos + 1, n));
return ans;
}
// Driver code
int main()
{
// size of the array
int n = 4;
int a[n] = { 1, 2, 3, 6 };
cout << maxSum(0, 0, a, 0, n);
return 0;
}
Java
// Java implementation for the
// above mentioned recursive approach
class GFG {
// Function to find the maximum subset sum
static int maxSum(int p0, int p1, int a[], int pos, int n)
{
if (pos == n) {
if (p0 == p1)
return p0;
else
return 0;
}
// Ignore the current element
int ans = maxSum(p0, p1, a, pos + 1, n);
// including element in partition 1
ans = Math.max(ans, maxSum(p0 + a[pos], p1, a, pos + 1, n));
// including element in partition 2
ans = Math.max(ans, maxSum(p0, p1 + a[pos], a, pos + 1, n));
return ans;
}
// Driver code
public static void main (String[] args)
{
// size of the array
int n = 4;
int a[] = { 1, 2, 3, 6 };
System.out.println(maxSum(0, 0, a, 0, n));
}
}
// This code is contributed by AnkitRai01
Python3
# Python3 implementation for the
# above mentioned recursive approach
# Function to find the maximum subset sum
def maxSum(p0, p1, a, pos, n) :
if (pos == n) :
if (p0 == p1) :
return p0;
else :
return 0;
# Ignore the current element
ans = maxSum(p0, p1, a, pos + 1, n);
# including element in partition 1
ans = max(ans, maxSum(p0 + a[pos], p1, a, pos + 1, n));
# including element in partition 2
ans = max(ans, maxSum(p0, p1 + a[pos], a, pos + 1, n));
return ans;
# Driver code
if __name__ == "__main__" :
# size of the array
n = 4;
a = [ 1, 2, 3, 6 ];
print(maxSum(0, 0, a, 0, n));
# This code is contributed by AnkitRai01
C#
// C# implementation for the
// above mentioned recursive approach
using System;
public class GFG {
// Function to find the maximum subset sum
static int maxSum(int p0, int p1, int []a, int pos, int n)
{
if (pos == n) {
if (p0 == p1)
return p0;
else
return 0;
}
// Ignore the current element
int ans = maxSum(p0, p1, a, pos + 1, n);
// including element in partition 1
ans = Math.Max(ans, maxSum(p0 + a[pos], p1, a, pos + 1, n));
// including element in partition 2
ans = Math.Max(ans, maxSum(p0, p1 + a[pos], a, pos + 1, n));
return ans;
}
// Driver code
public static void Main (string[] args)
{
// size of the array
int n = 4;
int []a = { 1, 2, 3, 6 };
Console.WriteLine(maxSum(0, 0, a, 0, n));
}
}
// This code is contributed by AnkitRai01
C++
// CPP implementation for the above mentioned
// Dynamic Programming approach
#include
using namespace std;
// Function to find the maximum subset sum
int maxSum(int a[], int n)
{
// sum of all elements
int sum = 0;
for (int i = 0; i < n; i++)
sum += a[i];
int limit = 2 * sum + 1;
// bottom up lookup table;
int dp[n + 1][limit];
// initialising dp table with INT_MIN
// where, INT_MIN means no solution
for (int i = 0; i < n + 1; i++) {
for (int j = 0; j < limit; j++)
dp[i][j] = INT_MIN;
}
// Case when diff is 0
dp[0][sum] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < limit; j++) {
// Putting ith element in g0
if ((j - a[i - 1]) >= 0 && dp[i - 1][j - a[i - 1]] != INT_MIN)
dp[i][j] = max(dp[i][j], dp[i - 1][j - a[i - 1]]
+ a[i - 1]);
// Putting ith element in g1
if ((j + a[i - 1]) < limit && dp[i - 1][j + a[i - 1]] != INT_MIN)
dp[i][j] = max(dp[i][j], dp[i - 1][j + a[i - 1]]);
// Ignoring ith element
if (dp[i - 1][j] != INT_MIN)
dp[i][j] = max(dp[i][j], dp[i - 1][j]);
}
}
return dp[n][sum];
}
// Driver code
int main()
{
int n = 4;
int a[n] = { 1, 2, 3, 6 };
cout << maxSum(a, n);
return 0;
}
Java
// Java implementation for the above mentioned
// Dynamic Programming approach
class GFG {
final static int INT_MIN = Integer.MIN_VALUE;
// Function to find the maximum subset sum
static int maxSum(int a[], int n)
{
// sum of all elements
int sum = 0;
for (int i = 0; i < n; i++)
sum += a[i];
int limit = 2 * sum + 1;
// bottom up lookup table;
int dp[][] = new int[n + 1][limit];
// initialising dp table with INT_MIN
// where, INT_MIN means no solution
for (int i = 0; i < n + 1; i++) {
for (int j = 0; j < limit; j++)
dp[i][j] = INT_MIN;
}
// Case when diff is 0
dp[0][sum] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < limit; j++) {
// Putting ith element in g0
if ((j - a[i - 1]) >= 0 && dp[i - 1][j - a[i - 1]] != INT_MIN)
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - a[i - 1]]
+ a[i - 1]);
// Putting ith element in g1
if ((j + a[i - 1]) < limit && dp[i - 1][j + a[i - 1]] != INT_MIN)
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j + a[i - 1]]);
// Ignoring ith element
if (dp[i - 1][j] != INT_MIN)
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j]);
}
}
return dp[n][sum];
}
// Driver code
public static void main (String[] args)
{
int n = 4;
int []a = { 1, 2, 3, 6 };
System.out.println(maxSum(a, n));
}
}
// This code is contributed by AnkitRai01
C#
// C# implementation for the above mentioned
// Dynamic Programming approach
using System;
class GFG {
static int INT_MIN = int.MinValue;
// Function to find the maximum subset sum
static int maxSum(int []a, int n)
{
// sum of all elements
int sum = 0;
for (int i = 0; i < n; i++)
sum += a[i];
int limit = 2 * sum + 1;
// bottom up lookup table;
int [,]dp = new int[n + 1,limit];
// initialising dp table with INT_MIN
// where, INT_MIN means no solution
for (int i = 0; i < n + 1; i++) {
for (int j = 0; j < limit; j++)
dp[i,j] = INT_MIN;
}
// Case when diff is 0
dp[0,sum] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < limit; j++) {
// Putting ith element in g0
if ((j - a[i - 1]) >= 0 && dp[i - 1,j - a[i - 1]] != INT_MIN)
dp[i,j] = Math.Max(dp[i,j], dp[i - 1,j - a[i - 1]]
+ a[i - 1]);
// Putting ith element in g1
if ((j + a[i - 1]) < limit && dp[i - 1,j + a[i - 1]] != INT_MIN)
dp[i,j] = Math.Max(dp[i,j], dp[i - 1,j + a[i - 1]]);
// Ignoring ith element
if (dp[i - 1,j] != INT_MIN)
dp[i,j] = Math.Max(dp[i,j], dp[i - 1,j]);
}
}
return dp[n,sum];
}
// Driver code
public static void Main()
{
int n = 4;
int []a = { 1, 2, 3, 6 };
Console.WriteLine(maxSum(a, n));
}
}
// This code is contributed by Yash_R
Python3
# Python3 implementation for the above mentioned
# Dynamic Programming approach
import numpy as np
import sys
INT_MIN = -(sys.maxsize - 1)
# Function to find the maximum subset sum
def maxSum(a, n) :
# sum of all elements
sum = 0;
for i in range(n) :
sum += a[i];
limit = 2 * sum + 1;
# bottom up lookup table;
dp = np.zeros((n + 1,limit));
# initialising dp table with INT_MIN
# where, INT_MIN means no solution
for i in range(n + 1) :
for j in range(limit) :
dp[i][j] = INT_MIN;
# Case when diff is 0
dp[0][sum] = 0;
for i in range(1, n + 1) :
for j in range(limit) :
# Putting ith element in g0
if ((j - a[i - 1]) >= 0 and dp[i - 1][j - a[i - 1]] != INT_MIN) :
dp[i][j] = max(dp[i][j], dp[i - 1][j - a[i - 1]]
+ a[i - 1]);
# Putting ith element in g1
if ((j + a[i - 1]) < limit and dp[i - 1][j + a[i - 1]] != INT_MIN) :
dp[i][j] = max(dp[i][j], dp[i - 1][j + a[i - 1]]);
# Ignoring ith element
if (dp[i - 1][j] != INT_MIN) :
dp[i][j] = max(dp[i][j], dp[i - 1][j]);
return dp[n][sum];
# Driver code
if __name__ == "__main__" :
n = 4;
a = [ 1, 2, 3, 6 ];
print(maxSum(a, n));
# This code is contributed by Yash_R
6
时间复杂度:
高效方法:
可以使用动态编程方法优化上述方法。
我们将定义DP状态如下:
dp[i][j] = Max sum of group g0 considering the first i elements such that,
the difference between the sum of g0 and g1 is (sum of all elements – j), where j is the difference.
So, the answer would be dp[n][sum]
现在我们可能会遇到,总和之间的差为负,范围为[-sum,+ sum],其中总和是所有元素的总和。当一个子集为空并且另一个子集具有所有元素时发生的最小和最大范围。因此,在DP状态下,我们将j定义为(sum – diff)。因此,j的范围为[0,2 * sum]。
下面是上述方法的实现:
C++
// CPP implementation for the above mentioned
// Dynamic Programming approach
#include
using namespace std;
// Function to find the maximum subset sum
int maxSum(int a[], int n)
{
// sum of all elements
int sum = 0;
for (int i = 0; i < n; i++)
sum += a[i];
int limit = 2 * sum + 1;
// bottom up lookup table;
int dp[n + 1][limit];
// initialising dp table with INT_MIN
// where, INT_MIN means no solution
for (int i = 0; i < n + 1; i++) {
for (int j = 0; j < limit; j++)
dp[i][j] = INT_MIN;
}
// Case when diff is 0
dp[0][sum] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < limit; j++) {
// Putting ith element in g0
if ((j - a[i - 1]) >= 0 && dp[i - 1][j - a[i - 1]] != INT_MIN)
dp[i][j] = max(dp[i][j], dp[i - 1][j - a[i - 1]]
+ a[i - 1]);
// Putting ith element in g1
if ((j + a[i - 1]) < limit && dp[i - 1][j + a[i - 1]] != INT_MIN)
dp[i][j] = max(dp[i][j], dp[i - 1][j + a[i - 1]]);
// Ignoring ith element
if (dp[i - 1][j] != INT_MIN)
dp[i][j] = max(dp[i][j], dp[i - 1][j]);
}
}
return dp[n][sum];
}
// Driver code
int main()
{
int n = 4;
int a[n] = { 1, 2, 3, 6 };
cout << maxSum(a, n);
return 0;
}
Java
// Java implementation for the above mentioned
// Dynamic Programming approach
class GFG {
final static int INT_MIN = Integer.MIN_VALUE;
// Function to find the maximum subset sum
static int maxSum(int a[], int n)
{
// sum of all elements
int sum = 0;
for (int i = 0; i < n; i++)
sum += a[i];
int limit = 2 * sum + 1;
// bottom up lookup table;
int dp[][] = new int[n + 1][limit];
// initialising dp table with INT_MIN
// where, INT_MIN means no solution
for (int i = 0; i < n + 1; i++) {
for (int j = 0; j < limit; j++)
dp[i][j] = INT_MIN;
}
// Case when diff is 0
dp[0][sum] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < limit; j++) {
// Putting ith element in g0
if ((j - a[i - 1]) >= 0 && dp[i - 1][j - a[i - 1]] != INT_MIN)
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - a[i - 1]]
+ a[i - 1]);
// Putting ith element in g1
if ((j + a[i - 1]) < limit && dp[i - 1][j + a[i - 1]] != INT_MIN)
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j + a[i - 1]]);
// Ignoring ith element
if (dp[i - 1][j] != INT_MIN)
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j]);
}
}
return dp[n][sum];
}
// Driver code
public static void main (String[] args)
{
int n = 4;
int []a = { 1, 2, 3, 6 };
System.out.println(maxSum(a, n));
}
}
// This code is contributed by AnkitRai01
C#
// C# implementation for the above mentioned
// Dynamic Programming approach
using System;
class GFG {
static int INT_MIN = int.MinValue;
// Function to find the maximum subset sum
static int maxSum(int []a, int n)
{
// sum of all elements
int sum = 0;
for (int i = 0; i < n; i++)
sum += a[i];
int limit = 2 * sum + 1;
// bottom up lookup table;
int [,]dp = new int[n + 1,limit];
// initialising dp table with INT_MIN
// where, INT_MIN means no solution
for (int i = 0; i < n + 1; i++) {
for (int j = 0; j < limit; j++)
dp[i,j] = INT_MIN;
}
// Case when diff is 0
dp[0,sum] = 0;
for (int i = 1; i <= n; i++) {
for (int j = 0; j < limit; j++) {
// Putting ith element in g0
if ((j - a[i - 1]) >= 0 && dp[i - 1,j - a[i - 1]] != INT_MIN)
dp[i,j] = Math.Max(dp[i,j], dp[i - 1,j - a[i - 1]]
+ a[i - 1]);
// Putting ith element in g1
if ((j + a[i - 1]) < limit && dp[i - 1,j + a[i - 1]] != INT_MIN)
dp[i,j] = Math.Max(dp[i,j], dp[i - 1,j + a[i - 1]]);
// Ignoring ith element
if (dp[i - 1,j] != INT_MIN)
dp[i,j] = Math.Max(dp[i,j], dp[i - 1,j]);
}
}
return dp[n,sum];
}
// Driver code
public static void Main()
{
int n = 4;
int []a = { 1, 2, 3, 6 };
Console.WriteLine(maxSum(a, n));
}
}
// This code is contributed by Yash_R
Python3
# Python3 implementation for the above mentioned
# Dynamic Programming approach
import numpy as np
import sys
INT_MIN = -(sys.maxsize - 1)
# Function to find the maximum subset sum
def maxSum(a, n) :
# sum of all elements
sum = 0;
for i in range(n) :
sum += a[i];
limit = 2 * sum + 1;
# bottom up lookup table;
dp = np.zeros((n + 1,limit));
# initialising dp table with INT_MIN
# where, INT_MIN means no solution
for i in range(n + 1) :
for j in range(limit) :
dp[i][j] = INT_MIN;
# Case when diff is 0
dp[0][sum] = 0;
for i in range(1, n + 1) :
for j in range(limit) :
# Putting ith element in g0
if ((j - a[i - 1]) >= 0 and dp[i - 1][j - a[i - 1]] != INT_MIN) :
dp[i][j] = max(dp[i][j], dp[i - 1][j - a[i - 1]]
+ a[i - 1]);
# Putting ith element in g1
if ((j + a[i - 1]) < limit and dp[i - 1][j + a[i - 1]] != INT_MIN) :
dp[i][j] = max(dp[i][j], dp[i - 1][j + a[i - 1]]);
# Ignoring ith element
if (dp[i - 1][j] != INT_MIN) :
dp[i][j] = max(dp[i][j], dp[i - 1][j]);
return dp[n][sum];
# Driver code
if __name__ == "__main__" :
n = 4;
a = [ 1, 2, 3, 6 ];
print(maxSum(a, n));
# This code is contributed by Yash_R
6
时间复杂度: ,其中Sum表示所有数组元素的总和。
辅助空间: