给定一组整数,找到可以从给定集合的子集生成的不同总和,并以升序打印。假设数组元素之和很小。
例子:
Input : arr[] = {1, 2, 3}
Output : 0 1 2 3 4 5 6
Distinct subsets of given set are
{}, {1}, {2}, {3}, {1,2}, {2,3},
{1,3} and {1,2,3}. Sums of these
subsets are 0, 1, 2, 3, 3, 5, 4, 6
After removing duplicates, we get
0, 1, 2, 3, 4, 5, 6
Input : arr[] = {2, 3, 4, 5, 6}
Output : 0 2 3 4 5 6 7 8 9 10 11 12
13 14 15 16 17 18 20
Input : arr[] = {20, 30, 50}
Output : 0 20 30 50 70 80 100
解决此问题的幼稚方法是生成所有子集,将它们的和存储在哈希集中,最后打印出哈希集中的所有键。
C++
// C++ program to print distinct subset sums of
// a given array.
#include
using namespace std;
// sum denotes the current sum of the subset
// currindex denotes the index we have reached in
// the given array
void distSumRec(int arr[], int n, int sum,
int currindex, unordered_set &s)
{
if (currindex > n)
return;
if (currindex == n)
{
s.insert(sum);
return;
}
distSumRec(arr, n, sum + arr[currindex],
currindex+1, s);
distSumRec(arr, n, sum, currindex+1, s);
}
// This function mainly calls recursive function
// distSumRec() to generate distinct sum subsets.
// And finally prints the generated subsets.
void printDistSum(int arr[], int n)
{
unordered_set s;
distSumRec(arr, n, 0, 0, s);
// Print the result
for (auto i=s.begin(); i!=s.end(); i++)
cout << *i << " ";
}
// Driver code
int main()
{
int arr[] = {2, 3, 4, 5, 6};
int n = sizeof(arr)/sizeof(arr[0]);
printDistSum(arr, n);
return 0;
}
Java
// Java program to print distinct
// subset sums of a given array.
import java.io.*;
import java.util.*;
class GFG
{
// sum denotes the current sum
// of the subset currindex denotes
// the index we have reached in
// the given array
static void distSumRec(int arr[], int n, int sum,
int currindex, HashSet s)
{
if (currindex > n)
return;
if (currindex == n) {
s.add(sum);
return;
}
distSumRec(arr, n, sum + arr[currindex],
currindex + 1, s);
distSumRec(arr, n, sum, currindex + 1, s);
}
// This function mainly calls
// recursive function distSumRec()
// to generate distinct sum subsets.
// And finally prints the generated subsets.
static void printDistSum(int arr[], int n)
{
HashSet s = new HashSet<>();
distSumRec(arr, n, 0, 0, s);
// Print the result
for (int i : s)
System.out.print(i + " ");
}
//Driver code
public static void main(String[] args)
{
int arr[] = { 2, 3, 4, 5, 6 };
int n = arr.length;
printDistSum(arr, n);
}
}
// This code is contributed by Gitanjali.
Python3
# Python 3 program to print distinct subset sums of
# a given array.
# sum denotes the current sum of the subset
# currindex denotes the index we have reached in
# the given array
def distSumRec(arr, n, sum, currindex, s):
if (currindex > n):
return
if (currindex == n):
s.add(sum)
return
distSumRec(arr, n, sum + arr[currindex], currindex+1, s)
distSumRec(arr, n, sum, currindex+1, s)
# This function mainly calls recursive function
# distSumRec() to generate distinct sum subsets.
# And finally prints the generated subsets.
def printDistSum(arr,n):
s = set()
distSumRec(arr, n, 0, 0, s)
# Print the result
for i in s:
print(i,end = " ")
# Driver code
if __name__ == '__main__':
arr = [2, 3, 4, 5, 6]
n = len(arr)
printDistSum(arr, n)
# This code is contributed by
# Surendra_Gangwar
C#
// C# program to print distinct
// subset sums of a given array.
using System;
using System.Collections.Generic;
class GFG
{
// sum denotes the current sum
// of the subset currindex denotes
// the index we have reached in
// the given array
static void distSumRec(int []arr, int n, int sum,
int currindex, HashSet s)
{
if (currindex > n)
return;
if (currindex == n)
{
s.Add(sum);
return;
}
distSumRec(arr, n, sum + arr[currindex],
currindex + 1, s);
distSumRec(arr, n, sum, currindex + 1, s);
}
// This function mainly calls
// recursive function distSumRec()
// to generate distinct sum subsets.
// And finally prints the generated subsets.
static void printDistSum(int []arr, int n)
{
HashSet s = new HashSet();
distSumRec(arr, n, 0, 0, s);
// Print the result
foreach (int i in s)
Console.Write(i + " ");
}
// Driver code
public static void Main()
{
int []arr = { 2, 3, 4, 5, 6 };
int n = arr.Length;
printDistSum(arr, n);
}
}
/* This code contributed by PrinciRaj1992 */
C++
// C++ program to print distinct subset sums of
// a given array.
#include
using namespace std;
// Uses Dynamic Programming to find distinct
// subset sums
void printDistSum(int arr[], int n)
{
int sum = 0;
for (int i=0; i
Java
// Java program to print distinct
// subset sums of a given array.
import java.io.*;
import java.util.*;
class GFG {
// Uses Dynamic Programming to
// find distinct subset sums
static void printDistSum(int arr[], int n)
{
int sum = 0;
for (int i = 0; i < n; i++)
sum += arr[i];
// dp[i][j] would be true if arr[0..i-1]
// has a subset with sum equal to j.
boolean[][] dp = new boolean[n + 1][sum + 1];
// There is always a subset with 0 sum
for (int i = 0; i <= n; i++)
dp[i][0] = true;
// Fill dp[][] in bottom up manner
for (int i = 1; i <= n; i++)
{
dp[i][arr[i - 1]] = true;
for (int j = 1; j <= sum; j++)
{
// Sums that were achievable
// without current array element
if (dp[i - 1][j] == true)
{
dp[i][j] = true;
dp[i][j + arr[i - 1]] = true;
}
}
}
// Print last row elements
for (int j = 0; j <= sum; j++)
if (dp[n][j] == true)
System.out.print(j + " ");
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 2, 3, 4, 5, 6 };
int n = arr.length;
printDistSum(arr, n);
}
}
// This code is contributed by Gitanjali.
Python3
# Python3 program to prdistinct subset
# Sums of a given array.
# Uses Dynamic Programming to find
# distinct subset Sums
def printDistSum(arr, n):
Sum = sum(arr)
# dp[i][j] would be true if arr[0..i-1]
# has a subset with Sum equal to j.
dp = [[False for i in range(Sum + 1)]
for i in range(n + 1)]
# There is always a subset with 0 Sum
for i in range(n + 1):
dp[i][0] = True
# Fill dp[][] in bottom up manner
for i in range(1, n + 1):
dp[i][arr[i - 1]] = True
for j in range(1, Sum + 1):
# Sums that were achievable
# without current array element
if (dp[i - 1][j] == True):
dp[i][j] = True
dp[i][j + arr[i - 1]] = True
# Print last row elements
for j in range(Sum + 1):
if (dp[n][j] == True):
print(j, end = " ")
# Driver code
arr = [2, 3, 4, 5, 6]
n = len(arr)
printDistSum(arr, n)
# This code is contributed
# by mohit kumar
C#
// C# program to print distinct
// subset sums of a given array.
using System;
class GFG {
// Uses Dynamic Programming to
// find distinct subset sums
static void printDistSum(int []arr, int n)
{
int sum = 0;
for (int i = 0; i < n; i++)
sum += arr[i];
// dp[i][j] would be true if arr[0..i-1]
// has a subset with sum equal to j.
bool [,]dp = new bool[n + 1,sum + 1];
// There is always a subset with 0 sum
for (int i = 0; i <= n; i++)
dp[i,0] = true;
// Fill dp[][] in bottom up manner
for (int i = 1; i <= n; i++)
{
dp[i,arr[i - 1]] = true;
for (int j = 1; j <= sum; j++)
{
// Sums that were achievable
// without current array element
if (dp[i - 1,j] == true)
{
dp[i,j] = true;
dp[i,j + arr[i - 1]] = true;
}
}
}
// Print last row elements
for (int j = 0; j <= sum; j++)
if (dp[n,j] == true)
Console.Write(j + " ");
}
// Driver code
public static void Main()
{
int []arr = { 2, 3, 4, 5, 6 };
int n = arr.Length;
printDistSum(arr, n);
}
}
// This code is contributed by nitin mittal.
输出:
0 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 20
上述幼稚递归方法的时间复杂度为O(2 n )。
使用动态规划可以改善上述问题的时间复杂度,尤其是当给定元素的总和较小时。我们可以制作一个dp表,其中的行包含数组的大小,而列的大小将是数组中所有元素的总和。
C++
// C++ program to print distinct subset sums of
// a given array.
#include
using namespace std;
// Uses Dynamic Programming to find distinct
// subset sums
void printDistSum(int arr[], int n)
{
int sum = 0;
for (int i=0; i
Java
// Java program to print distinct
// subset sums of a given array.
import java.io.*;
import java.util.*;
class GFG {
// Uses Dynamic Programming to
// find distinct subset sums
static void printDistSum(int arr[], int n)
{
int sum = 0;
for (int i = 0; i < n; i++)
sum += arr[i];
// dp[i][j] would be true if arr[0..i-1]
// has a subset with sum equal to j.
boolean[][] dp = new boolean[n + 1][sum + 1];
// There is always a subset with 0 sum
for (int i = 0; i <= n; i++)
dp[i][0] = true;
// Fill dp[][] in bottom up manner
for (int i = 1; i <= n; i++)
{
dp[i][arr[i - 1]] = true;
for (int j = 1; j <= sum; j++)
{
// Sums that were achievable
// without current array element
if (dp[i - 1][j] == true)
{
dp[i][j] = true;
dp[i][j + arr[i - 1]] = true;
}
}
}
// Print last row elements
for (int j = 0; j <= sum; j++)
if (dp[n][j] == true)
System.out.print(j + " ");
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 2, 3, 4, 5, 6 };
int n = arr.length;
printDistSum(arr, n);
}
}
// This code is contributed by Gitanjali.
Python3
# Python3 program to prdistinct subset
# Sums of a given array.
# Uses Dynamic Programming to find
# distinct subset Sums
def printDistSum(arr, n):
Sum = sum(arr)
# dp[i][j] would be true if arr[0..i-1]
# has a subset with Sum equal to j.
dp = [[False for i in range(Sum + 1)]
for i in range(n + 1)]
# There is always a subset with 0 Sum
for i in range(n + 1):
dp[i][0] = True
# Fill dp[][] in bottom up manner
for i in range(1, n + 1):
dp[i][arr[i - 1]] = True
for j in range(1, Sum + 1):
# Sums that were achievable
# without current array element
if (dp[i - 1][j] == True):
dp[i][j] = True
dp[i][j + arr[i - 1]] = True
# Print last row elements
for j in range(Sum + 1):
if (dp[n][j] == True):
print(j, end = " ")
# Driver code
arr = [2, 3, 4, 5, 6]
n = len(arr)
printDistSum(arr, n)
# This code is contributed
# by mohit kumar
C#
// C# program to print distinct
// subset sums of a given array.
using System;
class GFG {
// Uses Dynamic Programming to
// find distinct subset sums
static void printDistSum(int []arr, int n)
{
int sum = 0;
for (int i = 0; i < n; i++)
sum += arr[i];
// dp[i][j] would be true if arr[0..i-1]
// has a subset with sum equal to j.
bool [,]dp = new bool[n + 1,sum + 1];
// There is always a subset with 0 sum
for (int i = 0; i <= n; i++)
dp[i,0] = true;
// Fill dp[][] in bottom up manner
for (int i = 1; i <= n; i++)
{
dp[i,arr[i - 1]] = true;
for (int j = 1; j <= sum; j++)
{
// Sums that were achievable
// without current array element
if (dp[i - 1,j] == true)
{
dp[i,j] = true;
dp[i,j + arr[i - 1]] = true;
}
}
}
// Print last row elements
for (int j = 0; j <= sum; j++)
if (dp[n,j] == true)
Console.Write(j + " ");
}
// Driver code
public static void Main()
{
int []arr = { 2, 3, 4, 5, 6 };
int n = arr.Length;
printDistSum(arr, n);
}
}
// This code is contributed by nitin mittal.
输出:
0 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 20
上述方法的时间复杂度为O(n * sum),其中n是数组的大小,sum是数组中所有整数的总和。