Java 减少递归子集和算法的运行时间
我有一个递归DFS算法,可以正确地计算子集和的数量。然而,这种方法的运行时间是荒谬的,而且是指数级的。例如,当Java 减少递归子集和算法的运行时间,java,algorithm,recursion,big-o,subset-sum,Java,Algorithm,Recursion,Big O,Subset Sum,我有一个递归DFS算法,可以正确地计算子集和的数量。然而,这种方法的运行时间是荒谬的,而且是指数级的。例如,当arr包含以下集合时。我们要找的总数是50。arr已删除所有重复项和大于或等于50的数字。然后对数组进行排序 二十一, 3. 42 10 13 17 33 26 19 7. 11 30 24 2. 五, arr包含按排序顺序排列的单词列表 k是数组的初始大小 sum是我们在子集中查找的总和,在本例中为50 public static void recDfs(ArrayList<I
arr
包含以下集合时。我们要找的总数是50。arr
已删除所有重复项和大于或等于50的数字。然后对数组进行排序
二十一,
3.
42
10
13
17
33
26
19
7.
11
30
24
2.
五,
arr
包含按排序顺序排列的单词列表
k
是数组的初始大小
sum
是我们在子集中查找的总和,在本例中为50
public static void recDfs(ArrayList<Integer> arr, int k, int sum) {
if (sum == 0) {
counter++;
return;
}
if (sum != 0 && k == 0) {
return;
}
recDfs(arr, k - 1, sum - arr.get(k - 1));
recDfs(arr, k - 1, sum);
}
公共静态void recDfs(ArrayList arr、int k、int sum){
如果(总和=0){
计数器++;
返回;
}
如果(总和=0&&k==0){
返回;
}
recDfs(arr,k-1,sum-arr.get(k-1));
recDfs(arr,k-1,sum);
}
这将非常快地给出正确的结果,如下所示
经过的时间:=0.004838总计50的子集有51个
生成成功(总时间:0秒)
然而,当我们在数组中有一个新的集合时,该算法会呈指数增长,例如
九十九
49
1.
7.
23
83
72
6.
202
78
26
79
351
34
107
76
38
50
32
62
71
9
101
77
81
92
89
66
97
57
33
75
68
93
100
28
42
59
29
14
122
24
60
2.
37
192
73
84
31
4.
87
65
十九,
当我们使用新数组再次调用recDfs
时,新数组也会被排序并删除重复项(总和为107),运行时间是荒谬的,但是打印了正确数量的子集
经过的时间:=19853.771050总计107的子集数量为1845
构建成功(总时间:330分54秒)
我正在寻找更好的方法来实现这个算法 如果我正确理解这一点,可以进行一些小优化:
public static void recDfs(int[] arr, int k, int sum) {
if (sum < 0) return;
if (sum == 0) {
counter++;
return;
}
if (k == 0) {
return;
}
recDfs(arr, k - 1, sum - arr[k - 1]);
recDfs(arr, k - 1, sum);
}
publicstaticvoidrecdfs(int[]arr,int k,int sum){
如果(总和<0)返回;
如果(总和=0){
计数器++;
返回;
}
如果(k==0){
返回;
}
recDfs(arr,k-1,sum-arr[k-1]);
recDfs(arr,k-1,sum);
}
如果我正确地解释了这一点,那么如果总和小于0,您可以保留分支,这可以节省大量时间。(如果存在负数,则无法执行)其他次要优化是使用int数组。这应该比使用整数数组列表节省一些时间。如果你想变得更花哨,你可以使用多个线程。大提示:动态编程,记忆;)它也可以通过制表来完成,但是代码看起来会非常不同,因为您将自下而上而不是自上而下。无论如何,在DP中,这是一个很好的练习。