繁体   English   中英

C ++排序向量时间复杂度

[英]C++ sort vectors time complexity

假设我有一个带有N个向量的vector<vector<int>> L ,并且所有向量上的int s总数之和最多为M。标准C ++排序sort(L.begin(), L.end())吗?

vector<int>比较函数的运行时间最多为O(M),因此一个明显的界限是O(NM log N)。 但是,如果我们执行标准的mergesort,我们可以看到在每个O(log N)级别中最多完成了O(M)整数比较,因此运行时为O((N + M)log N)。 这是因为比较长度为A和B的两个向量需要O(min(A,B))时间。

C ++标准是否保证运行时为O((N + M)log N)?

没有足够的信息。 您还需要知道N向量上M值的分布 有了这些,就可以直接找到整体复杂性:

  1. std::sort具有O(N·log(N))比较的复杂度。

  2. std::vector使用std::lexicographical_compare(v1, v2)进行比较,比较复杂度为O(min(v1.size(), v2.size()))比较。

  3. int比较的复杂度为O(1)

  4. 我们会通知E(M, N)是在一个功能MN返回每一对内向量之间的最小元件平均数

    • 例如,如果您有一个均匀分布 ,则这等于M/N
  5. 取乘积: Big Oh = N·log(N)·E(M, N)·1
    • 对于均匀分布 ,这将是M·log(N)

您可以使用离散概率分布理论来计算E(M, N)函数对于MN任何分布的意义。


编辑1 :要弄清楚这种情况的重要性:考虑一个总是使我的向量看起来像的分布:

outer[0].size() == 1,
outer[1].size() == 1,
outer[2].size() == 1,
...,
outer[M-1].size() == (M - N + 1)

在这种情况下, E(M, N) = 1 ,因为std::lexicographical_compare只会有一个其他元素要与任何一对元素进行比较。 因此,对于这种特定的分布,我将始终具有O(N·log(N))的复杂度。 但是如果分布均匀,我将得到O(M·log(N))


编辑2 :在定义分布的注释之后,让我们尝试找到E(M, N)

首先,请注意总共有T = (N choose 2) = N(N - 1)(1/2)向量比较的不同组合。

一个(只有一个)组合将进行X = O((M - N + 2)(1/2))比较,并且发生概率P(X) = 1/T

其他所有组合仅需要1比较( O(1) ),因此这些情况的发生概率为P(1) = (T - 1)/T

求平均值很简单: X·P(X) + 1·P(1)

鉴于此, WolframAlpha说: E(M, N) = (M + (N - 2) N)/((N - 1) N)

该函数乘以N log(N)得到(M + (N - 2) N) log(N) / (N - 1) ,可以进一步简化为您要查找的Big Oh: O((M/N + N) log(N))

如果您的Integers 或多或少是随机的 1) ,大多数比较只需要比较每个向量的前几个整数(直到第一个不匹配),所以实际上/平均

M(反常)对算法复杂度没有任何影响

给你一些想法:即使向量有无限长并且最频繁出现的整数的p概率为50%, 平均您也需要进行少于2次比较

k < ∑ i*p^i = p/(1-p)^2 | p=0.5 
k < ∑ i*0.5^i = 2;

对于其他概率,结果为:

60% -> k <  2.5
70% -> k <  3.4
80% -> k <  5.0
90% -> k < 10.0

请记住,所有这些数字都是整数比较平均数的 上限 ,并且与向量中的元素数无关

1)随机是指密码意义上的随机。 这些数字甚至不必通过大多数随机数字质量测试。 唯一的要求是它们不能以系统的方式形成相同的前缀(随向量的长度而增长)。
除了恶意输入,我目前无法想到一个不符合“或多或少随机性”的现实示例,但可能还有其他情况。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM