算法的复杂度分析
complexity analysis of algorithm
这里是代码,它填充二维数组与随机生成的数字范围[1 19]没有重复,我的问题是:如何确定它的复杂性?
例如,我看到它的运行时间至少是O(n^2),因为它的内部和外部循环,但是关于goto
语句?
#include <iostream>
#include <set>
#include <cstdlib>
using namespace std;
int main()
{
int min=1;
int max=19;
int a[3][3];
set<int>b;
for (int i=0; i<3; i++)
{
for (int j=0; j<3; j++)
{
loop:
int m=min+rand()%(max-min);
if (b.find(m)==b.end())
{
a[i][j]=m;
b.insert(m);
}
else
goto loop;
}
}
for (int i=0; i<3; i++)
{
for (int j=0; j<3; j++)
cout<< a[i][j]<<" ";
cout<<endl;
}
return 0;
}
我会说算法的复杂度是c*O(n^2)其中c是某个常数,这是因为如果它在循环中发现重复的元素它会重复生成随机数并花费一些常数时间,对吗?
随着获得工作数的可能性降低,go -loop的数量增加。对于均匀随机数生成器,其行为与..的数量呈线性关系。数字。它绝对不会给你的复杂度增加一个常数。
如果n是a中元素的个数,那么它的平均比例为0 (n²)。(或者如果n是方阵a的行数;O (n⁴)).
一个更简单的实现是使用Fisher-Yates shuffle
它是0(∞)。0符号给出了一个上界。由于您在循环中使用了rand()
,因此无法保证您将取得进展。因此,不存在上界。
[编辑]好吧,除了传统的最坏情况的复杂性,人们还想要其他的复杂性。
假设RNG生成无穷个1的序列而得到的最坏情况复杂度;这意味着即使第一次循环迭代也没有完成。因此,在运行时间上没有有限的上界,O(∞)。
最佳情况下的复杂度是通过假设RNG生成序列号来获得的。即每次迭代的代价为O(log N) (set::find
),有O(N)*O(N)次迭代,因此上界为O(N2 log N)。
平均情况复杂度更难。假设max = k*N*N
对于某些k
> 1, RNG将在O(1)时间内成功地选择一个"未使用"的号码。即使选择了N*N个号码,仍然有(k-1)个未使用的号码,因此选择一个未使用的号码的机会p为p >= (k-1)*(N*N)/k*(N*N) <=> p>= (k-1)/k
。这意味着我们可以期望在k/(k-1)
尝试中选择一个未使用的数字,这与N无关,因此是O(1)。set::find
仍然主导每次迭代的成本,为O(log N)。我们仍然有相同的迭代次数,所以我们得到相同的上限O(N2 log N)
goto循环,直到一个随机数等于给定的数字。如果随机数的分布是均匀的,"retry…"直到"平均线性"相对于范围的振幅。但是这种线性会导致set::find (log(n)) (ste::insert只发生一次)的复杂度乘以
两个外部for是基于常量的(所以它们的计时不依赖于数据),因此它们只是乘以时间,但不会增加复杂性。
"复杂度"不是指你的程序占用了多少绝对时间(或空间)。它是关于当你增加程序输入数据的大小时,所增加的时间(或空间)。
(顺便说一下,O表示时间,O表示空间可能不同)
时间复杂度。假设n是矩阵中元素的数量,你必须问自己当你向矩阵中添加单个元素时会发生什么(即当n变成n+1时):
- 您需要遍历新元素,它是0(1)。这里我们讨论的是一次迭代,所以双循环并不重要。
- 您有另一个打印迭代,它也是0(1),假设
cout<<
是0(1)。 - 你必须
find
的元素是0 (log(n)) -std::set
通常实现为红黑树。 - 您必须重试
find
(通过goto
)可能几次。根据rnd
,min
,max
和int
的宽度,重试次数可能是0(1)(即它不随元素数量的增加而增加),也可能比这更糟。 - 你必须
insert
的元素是0 (log(n))。
假设"最佳"rnd
,您将看到以下元素增加…
(O (1) + O (1)) * (O (log (n)) * O (1) + O (log (n)) = O (1) * O (log (n)) = O (log (n))
…所以对于n个元素,复杂度是:
(O (n) + O (n)) * (O (log (n)) * O (1) + O (log (n)) = O (n) * O (log (n)) = O (n * log (n))
假设"坏"rnd
(0 (n)),您将看到…
空间复杂性(O (n) + O (n)) * (O (log (n)) * O (n) + O (log (n)) = O (n) * O (n * log (n)) = O (n ^ 2 * log (n))
你的矩阵是O(n), std::set
是O(n),所以你在这里总体上是O(n)。
- 为什么一种算法在相同的时间复杂度下比另一种算法更快?
- 如何降低 c++ 中算法的时间复杂度?
- 这个算法的运行时间复杂度是多少?你是如何分析的
- 如何证明以下算法具有 O(nlogn) 时间复杂度
- 三和算法的时间复杂度是多少
- 关于算法的时间复杂度
- 迭代算法的时间复杂度
- 气泡排序算法的空间复杂度.
- 最短路径的dijkstra算法的时间复杂度是否取决于所使用的数据结构?
- 这个算法的时间复杂度是多少
- 下面代码的算法复杂度是多少
- malloc()/free()/new/delete/delete[] 的算法复杂度是多少?
- 俄罗斯农民乘法算法的时间复杂度.
- 计算向量中值的最小差值的此函数的算法复杂度是多少
- 具有随机分量的算法的时间复杂度(吉莱斯皮算法)
- O(n^m) 复杂度的递归算法
- 编写算法以查找数组中最常出现的元素.给出算法的时间复杂度
- C++中strstr()函数的时间复杂度、空间复杂度和算法是什么
- 该算法的Big-O复杂度
- 这个算法的复杂度是多少?