循环时间复杂度内的递归
Recursion inside a loop time complexity
我创建此算法是为了使用回溯策略解决问题。问题在于:
Given a set A of n integers and two integer values, m and c. Calculate all subsets of A, of m elements, that the sum of their values is 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)。但是,在阅读了有关如何计算时间复杂度的指南后,我仍然无法从数学上确定这个结果。我对平均情况也很感兴趣,我很迷茫如何计算它。
我知道这可能是一个新手问题,但如果有人能帮助我,我将不胜感激!谢谢
您的算法的时间复杂度将为 O(m * 2^m)
,因为您考虑 A
的所有子集小于或等于 m
,因为您考虑 level
他们每个人!。乘以m
是为了求和每个子集的值。
该算法计算每个子集,假设 m=n。对于每个 0<=i<n
,您将 i-1
可能的子集数量加倍,因为 i-1
级别的每个子集有两种情况可以将它们带到 i
级别:添加 a[i]
,或者不添加。
例如,如果 i=2 并且有 4 个可能的子集(例如 {}、{A}、{B}、{AB}),那么对于 i=3 将有 4 个子集不包含 a[3]
(与之前相同),以及 4 个包含 a[3]
的新子集(例如 {C}、{AC}、{BC}、{ABC}),总共 8 个。
由于我们对每个 i<n
加倍,在 n=m 的情况下,可能的子集总数为 2^n
。
我创建此算法是为了使用回溯策略解决问题。问题在于:
Given a set A of n integers and two integer values, m and c. Calculate all subsets of A, of m elements, that the sum of their values is 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)。但是,在阅读了有关如何计算时间复杂度的指南后,我仍然无法从数学上确定这个结果。我对平均情况也很感兴趣,我很迷茫如何计算它。
我知道这可能是一个新手问题,但如果有人能帮助我,我将不胜感激!谢谢
您的算法的时间复杂度将为 O(m * 2^m)
,因为您考虑 A
的所有子集小于或等于 m
,因为您考虑 level
他们每个人!。乘以m
是为了求和每个子集的值。
该算法计算每个子集,假设 m=n。对于每个 0<=i<n
,您将 i-1
可能的子集数量加倍,因为 i-1
级别的每个子集有两种情况可以将它们带到 i
级别:添加 a[i]
,或者不添加。
例如,如果 i=2 并且有 4 个可能的子集(例如 {}、{A}、{B}、{AB}),那么对于 i=3 将有 4 个子集不包含 a[3]
(与之前相同),以及 4 个包含 a[3]
的新子集(例如 {C}、{AC}、{BC}、{ABC}),总共 8 个。
由于我们对每个 i<n
加倍,在 n=m 的情况下,可能的子集总数为 2^n
。