1 子集和问题(Subset Sum Problem)
给定一组非负整数和一个值和,确定给定集合中是否存在和等于给定和的子集。
示例:
输入:set[]={3,34,4,12,5,2},sum=9
输出:真
有一个子集(4,5)和9。
输入:设置[]={3,34,4,12,5,2},和=30
输出:False
没有加起来等于30的子集。
推荐做法
子集和问题
试试看!
方法1:递归。
方法:对于递归方法,我们将考虑两种情况。
考虑最后一个元素,现在所需的总和=目标总和–最后一个元素的值,元素数量=总元素–1
保留“最后一个”元素,现在所需的总和=目标总和,元素数=总元素数–1
以下是isSubsetSum()问题的递归公式。
IsubSetSum(集合,n,总和)
=IsubSetSum(集合,n-1,总和)| |
IsubSetSum(集合,n-1,和集合[n-1])
基本情况:
IsubSetSum(set,n,sum)=false,如果sum>0且n==0
IsubSetSum(set,n,sum)=真,如果sum==0
2 源代码
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;namespace Legalsoft.Truffer.Algorithm
{public static partial class Algorithm_Gallery{public static bool SubsetSum_Problem_Solve(int[] set, int n, int sum){if (sum == 0){return true;}if (n == 0){return false;}if (set[n - 1] > sum){return SubsetSum_Problem_Solve(set, n - 1, sum);}return SubsetSum_Problem_Solve(set, n - 1, sum) || SubsetSum_Problem_Solve(set, n - 1, sum - set[n - 1]);}public static bool SubsetSum_Problem_Solve_2th(int[] set, int n, int sum){bool[,] subset = new bool[sum + 1, n + 1];for (int i = 0; i <= n; i++){subset[0, i] = true;}for (int i = 1; i <= sum; i++){subset[i, 0] = false;}for (int i = 1; i <= sum; i++){for (int j = 1; j <= n; j++){subset[i, j] = subset[i, j - 1];if (i >= set[j - 1]){subset[i, j] = subset[i, j] || subset[i - set[j - 1], j - 1];}}}return subset[sum, n];}public static bool SubsetSum_Problem_Solve_3th(int[] set, int n, int sum){int[,] tab = new int[n + 1, sum + 1];for (int i = 1; i <= n; i++){for (int j = 1; j <= sum; j++){tab[i, j] = -1;}}if (sum == 0){return true;}if (n <= 0){return false;}if (tab[n - 1, sum] != -1){return tab[n - 1, sum] > 0;}if (set[n - 1] > sum){tab[n - 1, sum] = SubsetSum_Problem_Solve_3th(set, n - 1, sum) ? 1 : 0;return tab[n - 1, sum] > 0;}else{if (SubsetSum_Problem_Solve_3th(set, n - 1, sum) || SubsetSum_Problem_Solve_3th(set, n - 1, sum - set[n - 1])){tab[n - 1, sum] = 1;return true;}else{tab[n - 1, sum] = 0;return false;}}}}
}
3 源程序
using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
namespace Legalsoft.Truffer.Algorithm
{
public static partial class Algorithm_Gallery
{
public static bool SubsetSum_Problem_Solve(int[] set, int n, int sum)
{
if (sum == 0)
{
return true;
}
if (n == 0)
{
return false;
}
if (set[n - 1] > sum)
{
return SubsetSum_Problem_Solve(set, n - 1, sum);
}
return SubsetSum_Problem_Solve(set, n - 1, sum) ||
SubsetSum_Problem_Solve(set, n - 1, sum - set[n - 1]);
}
public static bool SubsetSum_Problem_Solve_2th(int[] set, int n, int sum)
{
bool[,] subset = new bool[sum + 1, n + 1];
for (int i = 0; i <= n; i++)
{
subset[0, i] = true;
}
for (int i = 1; i <= sum; i++)
{
subset[i, 0] = false;
}
for (int i = 1; i <= sum; i++)
{
for (int j = 1; j <= n; j++)
{
subset[i, j] = subset[i, j - 1];
if (i >= set[j - 1])
{
subset[i, j] = subset[i, j] || subset[i - set[j - 1], j - 1];
}
}
}
return subset[sum, n];
}
public static bool SubsetSum_Problem_Solve_3th(int[] set, int n, int sum)
{
int[,] tab = new int[n + 1, sum + 1];
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= sum; j++)
{
tab[i, j] = -1;
}
}
if (sum == 0)
{
return true;
}
if (n <= 0)
{
return false;
}
if (tab[n - 1, sum] != -1)
{
return tab[n - 1, sum] > 0;
}
if (set[n - 1] > sum)
{
tab[n - 1, sum] = SubsetSum_Problem_Solve_3th(set, n - 1, sum) ? 1 : 0;
return tab[n - 1, sum] > 0;
}
else
{
if (SubsetSum_Problem_Solve_3th(set, n - 1, sum) || SubsetSum_Problem_Solve_3th(set, n - 1, sum - set[n - 1]))
{
tab[n - 1, sum] = 1;
return true;
}
else
{
tab[n - 1, sum] = 0;
return false;
}
}
}
}
}