问题描述
我有以下计数排序,但空间复杂度对我来说太高了,我正在寻找一种方法来在 O(1) 的空间复杂度中做到这一点
df[
df[,"Category.1"] == df[,"Category.2"] |
sapply(1:nrow(df),function(x) {
df[x,"Value.1"] %in% List[[df[x,"Category.1"]]] &
df[x,"Value.2"] %in% List[[df[x,"Category.1"]]]
}),]
# Category.1 Value.1 Category.2 Value.2
# 1 A 0.2 A 0.0
# 2 A 0.2 B 0.3
# 4 B 0.2 B 0.2
目前,该算法正在分配 O(k) 空间。
假设 MyCountingSort(A,B,k)
for i = 0 to k
do G[i] = 0
for j = 0 to length[A]
do G[A[j]] = G[A[j]] + 1
for i = 1 to k
do G[i] = G[i] + G[i-1]
for j = length(A) to 1
do B[G[A[j]]] = A[j]
G[A[j]] = G[A[j]] - 1
,如何将算法空间复杂度提高到 O(1)?
解决方法
我在这里假设 A
是您的输入数组,B
是您的输出数组。因此,|A| = |B|
。我进一步假设 k
是我们可能遇到的最大数量的值(例如,如果 A
只包含从 1 到 k 或从 0 到 k-1)。如果您在提问时指定此类详细信息会对我们有所帮助,但我猜这或多或少是您要问的。 :)
由于我们有非常方便的附加约束 k <= |A|
,我们可以使用给定的数组 A
和 B
作为索引数组的中间存储。本质上,在您的代码中将 B
作为您的 G
并对其执行 1st 和 2nd 循环。然后我们进行累积加法(第三次循环)。
完成此操作后,我们可以将 B
复制回 A
。最后,我们用最终的排序数组覆盖 B
(代码中的第 4 个循环)。
这样,除了已经给出的输入参数之外,不会分配任何内存。通常,算法的空间复杂度被定义为与算法的输入无关。由于我们只是回收输入数组而不是自己分配任何东西,因此该算法确实具有 O(1) 空间复杂度。
请注意,在一般情况下(其中 k
不一定是 <= |A|
),不会这么容易。另外,只是因为输出数组B
已经作为输入提供给我们,我们可以利用这个“技巧”将它用于我们内部使用,因此不必分配任何新的内存.