我的代码的空间复杂度是多少

What is the space complexity of my code?

本文关键字:多少 空间复杂度 代码 我的      更新时间:2023-10-16

我对时间的复杂性足够满意,但对空间的复杂性还不够。 我有以下关于空间复杂性的问题:

unordered_set<int> s;
for(auto& i : nums)
s.insert(i);

根据我的理解,上述代码片段的空间复杂度是O(n)(n是输入向量nums中的元素数量),因为我在 for 循环之外创建集合并在其中最多插入n个元素。

但是,如果我在 for 循环中创建集合,例如:

for(auto& i : nums) {
unordered_set<int> s;
s.insert(i);
}

那么在这种情况下,我的空间复杂度会再次O(n)吗? 我知道我正在做的事情是不同的(每次创建一个新集合并在其中只插入一个元素),但我只是对空间复杂性感到好奇。

简而言之,空间复杂性是否仅取决于在数据结构中插入了多少元素,或者还取决于使用了多少数据结构(例如在循环中创建它们)。

谢谢。

在第二种情况下,空间复杂度O(1),第一种情况是O(n)

第二种情况..

如果每次声明本地unordered_set然后推送 1 个元素时都考虑循环中的第二种情况。然后没有使用,再次迭代。最多使用1或恒定的空间量。

第一种情况..

在第一种情况下,您采用set然后插入元素。最多插入n元素。这就是为什么O(n).

一些定义

对于每个大小的输入,算法将采用一定数量 的空间。在不过度复杂的情况下,您可以说也许它已被使用 存储输出或需要中间执行的一些工作。如何 您使用的许多数据结构不是问题,而是使用的空间 由他们。

空间

复杂性涉及找出算法在输入大小变化时需要多少(额外)空间。


现在让我们检查一件事,假设您将第一种情况下的输入数量从n=100增加到n=100000,那么您需要的额外内存是多少。正如您将看到的那样,它是线性增加的。(在100输入之前100集合的元素现在100000)。

在第二种情况下,您需要它吗?您始终只使用1空间。(恒定的空间量)。然后你丢弃它。在新的迭代中,您可以使用另一个空间。立刻只有1元素存在。因此,无论输入是什么,它都将始终相同。

更清楚的是,如果您在每次迭代中使用插入3元素,它不会改变空间复杂性。这仍然是O(1)时间复杂度,表示它使用恒定的空间量(无论输入大小如何)。

空间复杂度告诉您算法使用了多少内存。

在第二种情况下,您只将一个元素插入s.在那之后,s就超出了范围,你开始了新的迭代。这意味着您实际上一次只使用一个内存单元。内存使用量不会随n而增加。因此,您有O(1).

在第二种情况下,您的复杂性O(1)。 每次迭代将仅使用一次set,然后将被释放。

通常,复杂性取决于程序所需的总空间。 在您的情况下,您将使用大小为 1 的n倍集,但它不会累积。

在第二种情况下,循环体结束后,每个unordered_set将不复存在。一个合理的实现将对所有集合重用相同的空间,并且它们只包含一个元素。

如果将其用作空间复杂性指标,则第一种情况需要O(n)额外空间,第二种情况需要O(1)额外空间

空间复杂度是算法所需存储量如何相对于输入大小进行扩展的度量。

假设您插入n唯一的整数,除了一些不受插入其中的整数数影响的常量值之外,std::unordered_map确实必须分配足够的存储空间来存储n节点。因此,空间复杂度确实为 O(n)。

在第二个示例中,无论num中有多少个整数,您都将始终为std::unordered_set中的一个整数分配足够的存储空间。因此,空间复杂度为 O(1)。

从复杂性的角度来看,存储供应是无限的,重要的是您同时使用多少。

考虑测量X桶水的问题。
它对空间复杂性没有影响,无论您是否

有一个桶,你填满,然后清空,
  • 然后再次填满,然后清空,...,或
  • 装满
  • 一个桶并丢弃桶,然后装满另一个桶并将其扔掉,...

因为您在任何给定时间总是最多使用一个存储桶。
桶本身不计入复杂性,只计入您同时持有的桶的数量。

另一方面,如果你装满的不是一个,而是 X 个桶(也许你想为即将到来的干旱保存水),空间复杂度将是 O(X)。