所以我想知道整数对数组的空间复杂度是什么?
std::pair<int,int> arr[n];
我在想,因为一对是恒定的并且数组是n,所以空间复杂度是O(2) * O(n) = O(2n) = O(n)
。还是空间复杂度O(n^2)
因为对数组实际上仍然是2D数组?
答案 0 :(得分:5)
它在表面上类似于2D阵列这一事实并不重要:第二维的大小是已知的,因此它仍为O(n)。如果这些对是100个元素的数组,则也是如此。因为已知元素的尺寸(每个元素由100个元素组成的数组),所以结构的空间复杂度为O(100 * n),即O(n)。
但是,相反地,如果元素显式地始终与整个容器的大小相同,即类似于以下内容:
int n = /*...*/;
std::vector<std::vector<int>> arr(n);
for(std::vector<int> & subarr : arr) {
subarr.resize(n);
}
然后它的确是O(n 2 )。因为现在这两个维度都取决于未知数量。
反之,如果第二维未知,但已知与第一维不相关,则改为将其表示为O(nm),即像这样构造的数组:
int n = /*...*/;
int m = /*...*/;
std::vector<std::vector<int>> arr(n);
for(std::vector<int> & subarr : arr) {
subarr.resize(m);
}
现在这似乎是矛盾的:“但是Xirema,您只是说,如果我们知道,尺寸为n X 100个元素,则为O(n),但是如果我们替换100 for m,我们会不会有O(nm)或O(100n)的空间复杂度?”
但是就像我说的:我们删除已知数量。 O(2n)等于O(5n),因为我们所关心的只是未知数。一旦知道了未知数,我们在评估空间复杂度时就不再将其包括在内。
空间复杂度(和运行时复杂度等)旨在充当算法或数据结构的抽象表示。我们使用这些概念在较高的层次上确定它们扩展到越来越大的投入的程度。从小环境扩展到大环境时,两种不同的数据结构(一个元素每个元素需要100个字节,另一个元素每个元素需要4个字节的平方)在彼此之间不会具有一致的空间等级;在较小的环境中,后一种数据结构将消耗较少的内存,而在较大的环境中,前一种数据结构将消耗较少的内存。空间/运行时顺序的复杂性只是表达这种关系的一种简写,而无需陷入细节或语义上。如果您关心的是细节或语义,那么您将不只是使用结构/算法的顺序,而是要实际测试和衡量那些不同的方法。
答案 1 :(得分:4)
占用的空间为n * sizeof(std::pair<int, int>)
个字节。 sizeof(std::pair<int, int>)
是常量,O(n * (constant)) == O(n)
。
答案 2 :(得分:1)
数组的空间复杂度通常可以说是:
O(<size of array> * <size of each array element>)
您在这里:
std::pair<int,int> arr[n];
所以arr
是一个包含n
个元素的数组,每个元素都是一个std::pair<int,int>
。假设一个int
占用4个字节,因此两个int
对应该占用8个字节(根据实现的不同,这个数字可能会略有不同,但这对于复杂度计算的目的并不重要)。因此复杂度将为O(n * 8)
,与O(n)
相同,因为常量不会使复杂度有所不同。
什么时候会有O(n^2)
之类的东西?好吧,您将需要一个多维数组。例如,如下所示:
std::pair<int,int> arr[n][m];
现在arr
是一个包含m
个元素的数组,但是每个元素依次是n
std::pair<int,int>
个元素的数组。因此,您拥有O(m * <size of array of n pairs>)
,即O(m * n * 8)
,即O(m * n)
。如果m
恰好与n
相同,那么您将得到O(n * n)
或O(n^2)
。
您可以想象,对于任意数量的数组维,都遵循相同的推理。
答案 3 :(得分:-1)
编辑:
对不起,时间太复杂了。由于您知道结构中第二个元素的大小和数量(即不是n而是常数),因此空间复杂度保持不变,为O(n)