Description:
描述:
In this article, we are going to see how to solve the subset sum problem which has been featured in many interview rounds like Amazon, Microsoft?
在本文中,我们将看到如何解决在许多采访回合(如亚马逊,微软)中出现的子集和问题 ?
Problem statement:
问题陈述:
Given an array of size n and a sum K, determine whether any subset is possible with that sum or not. Print "yes" if there is any subset present else print "no".
给定大小为n的数组和总和K ,确定使用该总和是否可能存在任何子集。 如果存在任何子集,请打印“是” ,否则请打印“否” 。
Input & output:
In the first line the input will be n and K, space separated.
The next line contains the array elements
Output will be "yes" or "no"
Example with explanation:
带有说明的示例:
Example 1:
范例1:
Input:
The array size be: 5
The sum be: 11
The Elements be: 5 6 7 3 9
Output:
Yes
Explanation:
5 & 6 sums to 11. Thus the subset can be [5, 6] and output will be "yes".
Example 2:
范例2:
Input:
The array size be: 5
The sum be: 11
The Elements be: 5 6 7 3 9
Output:
Yes
Explanation:
5 & 6 sums to 11. Thus the subset can be [5, 6] and output will be "yes".
Solution Approach:
解决方法:
Of course the naïve solution would be to generate all possible subsets and check their sum equals to K or not. But it would of course be computationally exponential to generate all possible subsets.
当然,天真的解决方案是生成所有可能的子集,并检查它们的总和是否等于K。 但是,生成所有可能的子集在计算上当然是指数的。
To do so, the recursion would be:
为此,递归将是:
For nth element the cases are:
对于第 n 个元素,情况为:
Consider the nth element as part of solution subset and recur for n-1 elements for obtaining sum (K-arr[n]).
将第 n 个元素视为解决方案子集的一部分,然后对n-1个元素递归以获取总和(K-arr [n])。
Don't consider nth element as part of solution subset and recur for n-1 elements for obtaining sum (K).
不要将第 n 个元素视为解决方案子集的一部分,而是递归获取n-1个元素以获得和(K)。
So, the recursion function can be written as:
因此,递归函数可以写为:
f(n,K)=f(n-1,K) | f(n-1,K-arr[n-1])
Where,
哪里,
f(n,K)= value for problem with array size n and sum K which can be either true or false
Now base case would be,
现在的基本情况是
f(0,0) = true
f(0,i) = false for 1 ≤ i ≤K
f(i,0) = true 1 ≤ i ≤ n
Here comes the concept of sub problem. Initially the problem is for size n and sum K. Then it gets reduced to {size (n-1) and sum K} or {size (n-1) and (sum K-arr[n-1])}
这是子问题的概念。 最初,问题是大小为n和K的问题。然后,问题变为{大小(n-1)和K为总和}或{大小(n-1)和(sum K-arr [n-1])}
So if you draw the recursion tree there will be many such sub-problem which will be overlapping ones. That means we will re-compute same sub-problems again and again. That’s why we need to store the value of sub-problems and use dynamic programming.
因此,如果您绘制递归树,将会有很多这样的子问题,它们将是重叠的。 这意味着我们将一次又一次地重新计算相同的子问题。 这就是为什么我们需要存储子问题的值并使用动态编程的原因。
Converting to dynamic programming:
转换为动态编程:
1) Initialize dp[n+1][sum+1] which is a Boolean table to false
2) Convert the base cases for recursion
for i=1 to sum
dp[0][i]=false;
for i=0 to n
dp[i][0]=true;
3) Build the table as per the recursion formula.
for i=1 to sum
for j=1 to n
//if sub-sum i>jth element then only we can take that
if(i>=arr[j-1])
//consider both case mentioned in solution approach
dp[j][i]=dp[j-1][i] | dp[j-1][i-arr[j-1]];
else // don't take jth element
dp[j][i]=dp[j-1][i];
if(i==sum)
if(dp[j][i]){
return true;
End If
end for
end for
4) If not returned from the loop
return false;
C++ Implementation:
C ++实现:
#include <bits/stdc++.h>
using namespace std;
bool subsetSum(vector<int> arr, int n, int sum)
{
//DP matrix
bool dp[n + 1][sum + 1];
memset(dp, false, sizeof(dp));
//base case
for (int i = 1; i <= sum; i++)
dp[0][i] = false;
for (int i = 0; i <= n; i++)
dp[i][0] = true;
//build the table
for (int i = 1; i <= sum; i++) {
for (int j = 1; j <= n; j++) {
if (i >= arr[j - 1])
dp[j][i] = dp[j - 1][i] | dp[j - 1][i - arr[j - 1]];
else
dp[j][i] = dp[j - 1][i];
if (i == sum) {
if (dp[j][i]) {
return true;
}
}
}
}
return false;
}
int main()
{
int t, n, k, item;
cout << "Enter array length,n\n";
cin >> n;
cout << "Enter sum,K\n";
cin >> k;
cout << "Enter elements\n";
vector<int> a;
for (int j = 0; j < n; j++) {
scanf("%d", &item);
a.push_back(item);
}
if (subsetSum(a, n, k))
cout << "yes\n";
else
cout << "no\n";
return 0;
}
Output
输出量
RUN 1:
Enter array length,n
5
Enter sum,K
11
Enter elements
5 6 7 3 9
yes
RUN 2:
Enter array length,n
5
Enter sum,K
22
Enter elements
5 6 7 3 9
yes