我创建了此算法来使用回溯策略解决问题。问题在于:
给出由n个整数和两个整数值m和c组成的集合A。计算m个元素的A的所有子集,它们的值之和为c。
算法(在Java中):
public class Algorithm {
private List<Integer> a;
private int m;
private int c;
/**
* @param a Initial set
* @param m Maximum number of elements stored in the subset
* @param c Desired sum
*/
Algorithm(List<Integer> a, int m, int c) {
this.m = m;
this.c = c;
this.a = a;
findSubsets(0, new int[m], 0, 0);
}
/**
* @param i Index to go through the initial set
* @param subset Solution candidate
* @param level Current number of elements stored in the subset
* @param sum Current sum of the elements stored in the subset
*/
private void findSubsets(int i, int[] subset, int level, int sum) {
// Base case
if (level == m) {
if (sum == c) {
System.out.println(Arrays.toString(subset));
}
}
// Exploration
else {
while (i < a.size()) {
subset[level] = a.get(i);
findSubsets(i + 1, subset, level + 1, sum + a.get(i));
i++;
}
}
}
}
时间复杂度:
通过这种解决方案,我实验确定了当m趋于n时,复杂度趋于O(2 ^ n)。但是,在通读了有关如何计算时间复杂度的指南之后,我仍然无法从数学上确定该结果。我对平均情况也非常感兴趣,而我对如何计算它非常迷茫。
我知道这可能是一个新手问题,但是如果有人可以帮助我,我将不胜感激!谢谢
答案 0 :(得分:0)
当您考虑O(m * 2^m)
的所有子集时,算法的时间复杂度将为A
,因为您认为m
的所有子集小于或等于level
他们!。与m
的乘积用于求和每个子集的值。
答案 1 :(得分:0)
该算法计算每个子集,假设m = n。对于每个0<=i<n
,您将i-1
处的子集数量加倍,因为级别i-1
的每个子集有两种情况可以将它们带到i
级:添加a[i]
,否则不添加。
例如,如果i = 2并且有4个可能的子集(例如{},{A},{B},{AB}),那么对于i = 3,将有4个不包含{ {1}}(与之前相同),以及4个确实包含a[3]
的新子集(例如{C},{AC},{BC},{ABC}),总共8个。
由于我们为每个a[3]
加倍,因此在n = m的情况下,可能的子集总数为i<n
。