这包括一个"软件算法"来自https://stackoverflow.com/help/on-topic
这是来自课堂的演讲幻灯片
以下是我们使用的插入排序的实现
public static void insertionSort(int[] a) {
for (int i = 1; i < a.length; i++) {
int temp = a[i];
int j = i;
while (j >= 1 && a[j - 1] > temp) {
a[j] = a[j - 1];
}
a[j] = temp;
}
}
我同意局部变量的空间复杂度将是O(1),因为每次无论输入大小,i,j和temp都会占用一块内存,它只是相同的局部变量。
但是我对阵列的空间复杂性感到困惑。 http://www.cs.northwestern.edu/academics/courses/311/html/space-complexity.html有类似的例子,
int sum(int a[], int n) {
int r = 0;
for (int i = 0; i < n; ++i) {
r += a[i];
}
return r;
}
并说这个算法需要N个单位的内存用于a,这意味着它的空间复杂度是O(N)?
这是什么? O(N),因为数组需要N个存储单元(取决于输入大小)或O(1)因为通过引用传递?
答案 0 :(得分:6)
Array passed by reference
表示您就地排序,输出数据不需要额外的空间。
因此,空间复杂性(您需要的原始数据集(a))是常数O(1)
而不是线性O(n)
。
就最终的代码段而言, too 只是O(1)
,因为当传递给函数时,数组会降级为第一个元素指针。作者似乎在链接页面底部的评论中理解了这个概念:
但请注意。如果通过指针或引用传递内容,则共享空间。如果A将C样式数组传递给B,则没有分配新空间。
但是,出于某种原因,他们似乎相信传递数组会复制(b)。
(a)如果空间复杂度包含原始数据集,则O(1)
复杂性将不可能。
(b)而且,由于能够代表作者发言的最佳人选是作者本人,我提出了一个问题,并且答复解释了两个案例之间的区别。我希望他并不介意,因为作为一名教育工作者,我认为他有同样的&#34;增加 - 整体知识在世界上&#34;像我这样的态度,它表现出对我发现的那种态度的尊重程度:
额外空间通常称为辅助空间复杂度。没有限定符,空间复杂性包括输入空间要求。
我的网页至少应该参考这个区别。一个更好的页面将显示一些简单的实际例子,说明算法如何权衡时间,空间和算法的简单性,但由于我几年没有教过我们的数据结构课程,我还没有回来维护任何这些页面。我也不会声称自己是复杂性理论方面的专家。自然语言理解,基于案例的推理和敏捷软件开发是我的优势。
我认为它支持页面顶部关于缺乏关于空间复杂性的简单写作的声明,这个微不足道的页面在Google上的排名与它一样高。
感谢您与我联系,我希望这会有所帮助。
所以这似乎是术语上的差异而不是任何人的完全错误。我并非完全确定我看到了非辅助空间复杂度(包括原始数据集的大小)的有用性,因为无论选择何种算法,都会降低成本。< / p>
此外,我总是将复杂性视为算法的属性,并且由于所选择的算法无法控制原始数据集的大小,因此我倾向于不包括它
但是,我将来会更具体一点,确保我说明空间复杂性的含义,以防读者不确定: - )
无论如何,这至少说明了为什么你的课程笔记和西北大学的课程注意事项不同。无论您选择哪种空间复杂度定义,都应调整其中一个以将其考虑在内。
答案 1 :(得分:-1)
本质上两门课程都是一致的。
来自西北链接页面:
如果函数A使用其自身空间的M个单位(局部变量和参数),并且它调用需要N个单位局部空间的函数B,则A总体上需要M + N个临时工作空间单位。如果A呼叫B 3次怎么办?当一个函数完成时,它的空间可以被重用,所以如果A调用B 3次,它仍然只需要M + N个工作空间。
重点是功能 A 以及它需要多少空间,但解释暗示 B 复杂性没有考虑到 A 已经要求了。如果是这种情况,您可以证明程序的任何部分都需要与整个程序一样多的内存,这会使任何复杂性评估在实用性方面都非常有限。
将此应用于您的示例,该数组来自函数 A ,它调用 B (此处为函数sum
),并将数组传递给它。 sum
不分配或构造数组,也不需要复制它,因此它不计入sum
所需的内容。
答案 2 :(得分:-1)
我认为来自西北的作者是不正确的。用于函数的空间取决于传递给函数的空间大小,但在函数使用期间在函数中分配了多少空间。
在总和示例中,在调用函数之前分配空间,并且未在函数内分配空间,因此它将计入空间使用量。