java - 减少递归子集求和算法的运行时间

标签 java algorithm recursion big-o subset-sum

我有一个递归 DFS 算法,可以正确计算子集总和的数量。然而,这种方法的运行时间是荒谬的,而且呈指数级增长。例如,当 arr 包含以下集合时。我们正在寻找的总和是 50。arr 删除了所有重复项和大于或等于 50 的数字。然后对数组进行排序。

21 3个 42 10 13 17 33 26 19 7 11 30 24 2个 5

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);
}

这将非常快速地给出正确的结果,在下面发布

耗时:= 0.004838有 51 个子集总和为 50 构建成功(总时间:0 秒)

但是,当我们在数组中有一个新集合时,这个算法会呈指数增长,例如。

99 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 19

当我们再次使用新数组调用 recDfs 时,新数组也经过排序并删除了重复项,总和为 107,运行时间是荒谬的,但是打印了正确数量的子集。

耗时:= 19853.771050有 1845 个子集总和为 107 构建成功(总时间: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);
}

如果我对此的解释正确,那么如果总和小于 0,您可以放弃分支,这可以节省很多时间。 (如果有负数则无法完成)其他较小的优化是使用 int 数组。这应该比使用整数 ArrayList 节省一点时间。如果你想变得花哨,你可以使用多线程。

关于java - 减少递归子集求和算法的运行时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28835145/

相关文章:

python - 确保一个 Action 在递归调用期间只发生一次

java - 通过 JNDI 将 Tomcat 连接到独立的 Artemis Broker

algorithm - 将表示对象所有维度的一组 2d 图像转换为 3d 模型

Java:具有并行数组的快速排序算法

r - 用 R 中的数值迭代器改进收敛算法

haskell - 这个斐波那契序列函数是递归的吗?

mysql - 如何深入mysql存储过程递归?

java - 将数组写入文件

java - 比较两种选择排序方法

java - Robolectric::LayoutInflator.inflate() 卡在 onCreateOptionsMenu 中