算法复杂度分析
这是代码,它用[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 是某个常数,这是因为如果它在循环内找到重复的元素,它会重复生成随机数并需要一些恒定的时间,am我说得对吗?
here is code, which fills two dimensional array with random genarated numbers in range [1 19] without duplication, my question is: how to determine it's complexity?
For example, I see that its running time is at least O(n^2), because of its inner and outer cycles, but that about the goto
statement?
Here is my code:
#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;
}
I would say that complexity of algorithm is c*O(n^2) where c is some constant, it is because if it finds duplicated element inside cycles it repeats generation of random numbers and takes some constant time, am I right?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
随着获得工作编号的可能性降低,goto 循环的数量会增加。
对于均匀随机数生成器,其行为与数字的数量呈线性关系。它绝对不会增加你的复杂性。
如果 n 是 a 中的元素数量,那么它的平均规模为 O(n²)。 (或者如果 n 是方阵 a 中的行数;O(n⁴))。
更简单的实现是使用 Fisher-Yates shuffle
As the likelihood of getting a working number decreases, the number of goto-loops increases.
For a uniform random number generator, the behavior is linear with respect to the number of.. numbers. It definitely doesn't add a constant to your complexity.
If n is the number of elements in a, then it'll on average scale with O(n²). (or if n is the number of rows in the square matrix a; O(n⁴)).
A much simpler implementation would be using Fisher-Yates shuffle
是O(无穷大)。 O 表示法给出了上限。由于您在循环中使用了
rand()
,因此无法保证您会取得进展。因此,不存在上限。[编辑]
好吧,除了传统的、最坏情况的复杂性之外,人们还想要其他的复杂性。
假设 RNG 生成无限级数得到的最坏情况复杂度;这意味着即使第一次循环迭代也没有完成。因此,运行时间没有有限上限,O(无穷大)。
最好情况的复杂度是通过假设 RNG 生成序列数来获得的。这意味着每次迭代的成本为 O(log N) (
set::find
),并且有 O(N)*O(N) 次迭代,因此上限为 O(N< support>2 log N)。平均情况的复杂性更难。假设对于某些
k
> max = k*N*N 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) 上限It's O(infinity). The O notation gives an upper bound. Because of your use of
rand()
in a loop, there's no guarantee that you will make progress. Therefore, no upper bound exists.[edit]
Ok, people also want other complexities than the conventional, worst-case complexity.
The worst-case complexity obtained by assuming that the RNG generates an infinite series of ones; this means that even the first loop iteration doesn't finish. Therefore there's no finite upper bound on the run time, O(infinity).
The best-case complexity is obtained by assuming that the RNG generates sequential numbers. That means the cost of each iteration is O(log N) (
set::find
), and there are O(N)*O(N) iterations, so the upper bound is O(N2 log N).The average case complexity is harder. Assuming that
max = k*N*N
for somek
> 1, the RNG will succesfully pick an "unused" number in O(1) time. Even after N*N numbers are chosen, there are still (k-1) unused numbers, so the chance p of picking an unused number isp >= (k-1)*(N*N)/k*(N*N) <=> p>= (k-1)/k
. That means we can expect to pick an unused number ink/(k-1)
attempts, which is independent of N and therefore O(1).set::find
still dominates the cost of each iteration, at O(log N). We still have the same number of iterations, so we get the same upper bound of O(N2 log N)goto 循环直到随机数等于给定数。
如果随机数的分布是均匀的,则“重试...直到”相对于范围的幅度是“平均线性”。
但是这种线性会增加 set::find (log(n)) 的复杂性(ste::insert 仅发生一次)
两个外部 for 基于常量(因此它们的时间不依赖于数据),因此它们只会增加时间,但不会增加复杂性。
The goto loops until a random number equals a given one.
if the distribution of random numbers is uniform, "retry ... until" is "linear in average" respect to the amplitude of the range.
But this linearity gos to multiply the complexity of set::find (log(n)) (ste::insert just happen once)
The two external for are based on constants (so their timing doesn't depend on the data), hence they just multiply the time, but don't increase complexity.
“复杂性”并不是你的程序需要多少绝对时间(或空间)。它是关于当您增加程序输入数据的大小时增加时间(或空间)的量。
(顺便说一句,表示时间的 O 和表示空间的 O 可能不同。)
时间复杂度
假设 n 是矩阵中的元素数量,您必须问自己添加时会发生什么矩阵中的单个元素(即,当 n 变为 n+1 时):
找到
O(log(n)) 的元素 -std::set
通常实现为红黑树。find
(通过goto
)多次。根据rnd
、min
、max
和int
的宽度,重试次数可能为 O(1) (即它不会随着元素数量的增加而增加)或者可能比这更糟。插入
O(log(n)) 的元素。假设“最佳”
rnd
,您将看到一个元素的以下增加......所以对于 n 个元素,您的复杂性是:
假设 O(n) 的“坏”
rnd
,你正在看......空间复杂度
你的矩阵是 O(n) ,而 std::set 是 O(n) 所以你总体上是 O(n) 。
"Complexity" is not about how much absolute time (or space) your program takes. It is about how much the time (or space) increases when you increase the size of your program's input data.
(BTW O for time and O for space may be different.)
Time Complexity
Assuming n is number of elements in the matrix, you have to ask yourself what happens when you add a single element to your matrix (i.e. when n becomes n+1):
cout<<
is O(1).find
the element which is O(log(n)) - thestd::set
is typically implemented as a red-black tree.find
(viagoto
) potentially several times. Depending onrnd
,min
,max
and the width ofint
, number of retries may be O(1) (i.e. it does not increase with increase in number of elements) or it may be worse than that.insert
the element which is O(log(n)).Assuming the "best"
rnd
, you are looking at the following increase for one element......so for n elements, your complexity is:
Assuming "bad"
rnd
of O(n), you are looking at...Space Complexity
Your matrix is O(n) and
std::set
is O(n) so you are O(n) here overall.