算法复杂度分析

发布于 2024-12-05 03:49:31 字数 912 浏览 1 评论 0原文

这是代码,它用[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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

恏ㄋ傷疤忘ㄋ疼 2024-12-12 03:49:31

随着获得工作编号的可能性降低,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

旧情别恋 2024-12-12 03:49:31

是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) 个未使用的号码,因此选择未使用号码的几率 pp >= (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 some k > 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 is p >= (k-1)*(N*N)/k*(N*N) <=> p>= (k-1)/k. That means we can expect to pick an unused number in k/(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)

断肠人 2024-12-12 03:49:31

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.

↘紸啶 2024-12-12 03:49:31

“复杂性”并不是你的程序需要多少绝对时间(或空间)。它是关于当您增加程序输入数据的大小时增加时间(或空间)的量。

(顺便说一句,表示时间的 O 和表示空间的 O 可能不同。)

时间复杂度

假设 n 是矩阵中的元素数量,您必须问自己添加时会发生什么矩阵中的单个元素(即,当 n 变为 n+1 时):

  • 您需要迭代新元素,时间复杂度为 O(1)。我们在这里讨论的是一次迭代,因此双循环并不重要。
  • 您还有另一个打印迭代,这也是 O(1),假设 cout<< 是 O(1)。
  • 您必须找到 O(log(n)) 的元素 - std::set 通常实现为红黑树。
  • 您可能必须重试find(通过goto)多次。根据 rndminmaxint 的宽度,重试次数可能为 O(1) (即它不会随着元素数量的增加而增加)或者可能比这更糟。
  • 您必须插入 O(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))

假设 O(n) 的“坏”rnd,你正在看......

(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) 。

"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):

  • You need to iterate over the new element, which is O(1). We are talking about one iteration here, so double loop does not matter.
  • You have another iteration for printing, which is also O(1), assuming cout<< is O(1).
  • You have to find the element which is O(log(n)) - the std::set is typically implemented as a red-black tree.
  • You have to retry the find (via goto) potentially several times. Depending on rnd, min, max and the width of int, 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.
  • You have to insert the element which is O(log(n)).

Assuming the "best" rnd, you are looking at the following increase for one element...

(O(1) + O(1)) * (O(log(n)) * O(1) + O(log(n)) = O(1) * O(log(n)) = O(log(n))

...so for n elements, your complexity is:

(O(n) + O(n)) * (O(log(n)) * O(1) + O(log(n)) = O(n) * O(log(n)) = O(n * log(n))

Assuming "bad" rnd of O(n), you are looking at...

(O(n) + O(n)) * (O(log(n)) * O(n) + O(log(n)) = O(n) * O(n * log(n)) = O(n^2 * log(n))

Space Complexity

Your matrix is O(n) and std::set is O(n) so you are O(n) here overall.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文