给定一个整数数组和一个总和,任务是打印给定数组的所有子集,其总和等于给定的总和。
例子:
Input : arr[] = {2, 3, 5, 6, 8, 10}
sum = 10
Output : 5 2 3
2 8
10
Input : arr[] = {1, 2, 3, 4, 5}
sum = 10
Output : 4 3 2 1
5 3 2
5 4 1
在 Tesco 询问
这个问题主要是子集和问题的扩展。这里我们不仅需要查找是否存在具有给定和的子集,还需要打印具有给定和的所有子集。
和上一篇文章一样,我们构建了一个二维数组 dp[][] ,如果从 0 到 i 的数组元素可以求和 j ,则 dp[i][j] 存储真。
填充dp[][]后,我们从dp[n-1][sum]开始递归遍历。对于被遍历的单元格,我们在到达它之前存储路径并考虑元素的两种可能性。
1) 元素包含在当前路径中。
2) 元素不包含在当前路径中。
每当总和变为 0 时,我们停止递归调用并打印当前路径。
下面是上述想法的一个实现。
C++
// C++ program to count all subsets with
// given sum.
#include
using namespace std;
// dp[i][j] is going to store true if sum j is
// possible with array elements from 0 to i.
bool** dp;
void display(const vector& v)
{
for (int i = 0; i < v.size(); ++i)
printf("%d ", v[i]);
printf("\n");
}
// A recursive function to print all subsets with the
// help of dp[][]. Vector p[] stores current subset.
void printSubsetsRec(int arr[], int i, int sum, vector& p)
{
// If we reached end and sum is non-zero. We print
// p[] only if arr[0] is equal to sun OR dp[0][sum]
// is true.
if (i == 0 && sum != 0 && dp[0][sum])
{
p.push_back(arr[i]);
// Display Only when Sum of elements of p is equal to sum
if (arr[i] == sum)
display(p);
return;
}
// If sum becomes 0
if (i == 0 && sum == 0)
{
display(p);
return;
}
// If given sum can be achieved after ignoring
// current element.
if (dp[i-1][sum])
{
// Create a new vector to store path
vector b = p;
printSubsetsRec(arr, i-1, sum, b);
}
// If given sum can be achieved after considering
// current element.
if (sum >= arr[i] && dp[i-1][sum-arr[i]])
{
p.push_back(arr[i]);
printSubsetsRec(arr, i-1, sum-arr[i], p);
}
}
// Prints all subsets of arr[0..n-1] with sum 0.
void printAllSubsets(int arr[], int n, int sum)
{
if (n == 0 || sum < 0)
return;
// Sum 0 can always be achieved with 0 elements
dp = new bool*[n];
for (int i=0; i p;
printSubsetsRec(arr, n-1, sum, p);
}
// Driver code
int main()
{
int arr[] = {1, 2, 3, 4, 5};
int n = sizeof(arr)/sizeof(arr[0]);
int sum = 10;
printAllSubsets(arr, n, sum);
return 0;
}
Java
// A Java program to count all subsets with given sum.
import java.util.ArrayList;
public class SubSet_sum_problem
{
// dp[i][j] is going to store true if sum j is
// possible with array elements from 0 to i.
static boolean[][] dp;
static void display(ArrayList v)
{
System.out.println(v);
}
// A recursive function to print all subsets with the
// help of dp[][]. Vector p[] stores current subset.
static void printSubsetsRec(int arr[], int i, int sum,
ArrayList p)
{
// If we reached end and sum is non-zero. We print
// p[] only if arr[0] is equal to sun OR dp[0][sum]
// is true.
if (i == 0 && sum != 0 && dp[0][sum])
{
p.add(arr[i]);
display(p);
p.clear();
return;
}
// If sum becomes 0
if (i == 0 && sum == 0)
{
display(p);
p.clear();
return;
}
// If given sum can be achieved after ignoring
// current element.
if (dp[i-1][sum])
{
// Create a new vector to store path
ArrayList b = new ArrayList<>();
b.addAll(p);
printSubsetsRec(arr, i-1, sum, b);
}
// If given sum can be achieved after considering
// current element.
if (sum >= arr[i] && dp[i-1][sum-arr[i]])
{
p.add(arr[i]);
printSubsetsRec(arr, i-1, sum-arr[i], p);
}
}
// Prints all subsets of arr[0..n-1] with sum 0.
static void printAllSubsets(int arr[], int n, int sum)
{
if (n == 0 || sum < 0)
return;
// Sum 0 can always be achieved with 0 elements
dp = new boolean[n][sum + 1];
for (int i=0; i p = new ArrayList<>();
printSubsetsRec(arr, n-1, sum, p);
}
//Driver Program to test above functions
public static void main(String args[])
{
int arr[] = {1, 2, 3, 4, 5};
int n = arr.length;
int sum = 10;
printAllSubsets(arr, n, sum);
}
}
//This code is contributed by Sumit Ghosh
Java
// Java code to find the number of
// possible subset with given sum
import java.util.*;
import java.lang.*;
import java.io.*;
class GFG {
static int count;
static int sum;
static int n;
// Driver code
public static void main (String[] args) {
count = 0;
n = 5;
sum = 10;
int[] pat = {2, 3, 5, 6, 8, 10};
f(pat, 0, 0);
System.out.println(count);
}
// Function to select or not the array element
// to form a subset with given sum
static void f(int[] pat, int i, int currSum) {
if (currSum == sum) {
count++;
return;
}
if (currSum < sum && i < n) {
f(pat, i+1, currSum + pat[i]);
f(pat, i+1, currSum);
}
}
}
输出:
4 3 2 1
5 3 2
5 4 1
另一种方法:
对于数组中的每个元素,首先决定是否将其放入子集中。定义一个函数来处理所有这些。该函数在主函数被调用一次。声明了静态类字段,这些字段将由我们的函数操作。每次调用时,该函数检查字段的条件。在我们的例子中,它检查当前的总和是否等于给定的总和,并相应地增加相应的类字段。如果不是,它通过处理所有情况进行函数调用。所以函数调用的数量将等于案例的数量。因此,这里进行了两次调用——一次通过获取子集中的元素并增加当前总和,另一次通过不获取该元素。
下面是实现:
Java
// Java code to find the number of
// possible subset with given sum
import java.util.*;
import java.lang.*;
import java.io.*;
class GFG {
static int count;
static int sum;
static int n;
// Driver code
public static void main (String[] args) {
count = 0;
n = 5;
sum = 10;
int[] pat = {2, 3, 5, 6, 8, 10};
f(pat, 0, 0);
System.out.println(count);
}
// Function to select or not the array element
// to form a subset with given sum
static void f(int[] pat, int i, int currSum) {
if (currSum == sum) {
count++;
return;
}
if (currSum < sum && i < n) {
f(pat, i+1, currSum + pat[i]);
f(pat, i+1, currSum);
}
}
}
输出 :
4 3 2 1
5 3 2
5 4 1
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。