データ構造(1)-時間の複雑さの問題

時間の複雑さ

アルゴリズム関数の実行回数を取得するT(n)==>アルゴリズムの時間の複雑さを取得する

1.定数項は関数の成長率にほとんど影響を与えないことがわかっているため、T(n)= cでcが定数の場合、このアルゴリズムの時間の複雑さはO(1)であると言います。T(n )定数項と等しくない場合は、定数項を直接省略してください。

比如
 T(n) = 2,(算法)的时间复杂度为 O(1)。
T(n) = n + 29,此时时间复杂度为 O(n)。

2.高次の項が関数の成長率に最大の影響を与えることを私たちは知っています。n ^ 3の成長率はn ^ 2よりもはるかに速く、n ^ 2の成長率はnよりもはるかに速いです。同時に、必要な精度が高くないため、低い項目は直接無視します。

比如
T(n) = n^3 + n^2 + 29,此时时间复杂度为 O(n^3)。

3.関数の次数は関数の成長率に最も大きな影響を与えるため、定数に最高次数を掛けたものは無視します。

比如
T(n) = 3n^3,此时时间复杂度为 O(n^3)。

まとめると、アルゴリズムの実行回数がT(n)の場合、最上位の項のみが保持され、最上位の項の係数は同時に無視されて関数f(n)が得られます。このとき、アルゴリズムの時間の複雑さはO(f(n)です。 )

小さな例

1.ループの場合、ループ本体の時間の複雑さをO(n)、ループの数をmとすると
このループの時間の複雑さはO(n×m)になります。

void aFunc(int n) {
    for(int i = 0; i < n; i++) {         // 循环次数为 n
        printf("Hello, World!\n");      // 循环体时间复杂度为 O(1)
    }
}

このとき、時間の複雑さはO(n×1)、つまりO(n)です。

2.複数のループの場合、ループ本体の時間の複雑さがO(n)であり、各ループのループ時間がa、b、c ...であるとすると、このループの時間の複雑さはO(n×a×b× c ...)。分析するときは、これらのサイクルを裏返しに分析する必要があります。

void aFunc(int n) {
    for(int i = 0; i < n; i++) {         // 循环次数为 n
        for(int j = 0; j < n; j++) {       // 循环次数为 n
            printf("Hello, World!\n");      // 循环体时间复杂度为 O(1)
        }
    }
}

このとき、時間の複雑さはO(n×n×1)、つまりO(n ^ 2)です。

3.順次実行されるステートメントまたはアルゴリズムの場合、合計時間の複雑さは最大の時間の複雑さに等しくなります。

void aFunc(int n) {
    // 第一部分时间复杂度为 O(n^2)
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            printf("Hello, World!\n");
        }
    }
    // 第二部分时间复杂度为 O(n)
    for(int j = 0; j < n; j++) {
        printf("Hello, World!\n");
    }
}

このとき、時間の複雑さはmax(O(n ^ 2)、O(n))、つまりO(n ^ 2)です。

4.条件付き判断ステートメントの場合、合計時間の複雑さは、時間の複雑さが最大のパスの時間の複雑さに等しくなります。

void aFunc(int n) {
    if (n >= 0) {
        // 第一条路径时间复杂度为 O(n^2)
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                printf("输入数据大于等于零\n");
            }
        }
    } else {
        // 第二条路径时间复杂度为 O(n)
        for(int j = 0; j < n; j++) {
            printf("输入数据小于零\n");
        }
    }
}

このとき、時間の複雑さはmax(O(n ^ 2)、O(n))、つまりO(n ^ 2)です。

運動

基本的な質問

void aFunc(int n) {
    for (int i = 0; i < n; i++) {
        for (int j = i; j < n; j++) {
            printf("Hello World\n");
        }
    }
}

回答:T(n)= n + n-1 + n-2…+ 1 = n(n + 1)/
2O(n)= n 2

高度な質問

void aFunc(int n) {
    for (int i = 2; i < n; i++) {
        i *= 2;
        printf("%i\n", i);
    }
}

回答:サイクル数をtとすると、サイクル条件は2 ^ t <nを満たします。
実行回数t = log(2)(n)、つまりT(n)= log(2)(n)であると結論付けることができ、時間の複雑さはO(log(2)(n))、つまりO(log)であることがわかります。 n)。

再び進んだ

long aFunc(int n) {
    if (n <= 1) {
        return 1;
    } else {
        return aFunc(n - 1) + aFunc(n - 2);
    }
}

回答:明らかに、実行回数はT(0)= T(1)= 1であり、同時にT(n)= T(n-1)+ T(n-2)+ 1です。ここで、1は加算の1回の実行です。 。
明らかに、T(n)= T(n-1)+ T(n-2)はフィボナッチシーケンスです。n> = 1の場合、T(n)<(5/3)であることが誘導証明によって証明できます。 ^ n、およびn> 4の場合、T(n)> =(3/2)^ n。
したがって、このメソッドの時間の複雑さはO((5/3)^ n)として表すことができ、これはO(2 ^ n)として簡略化されます。

おすすめ

転載: blog.csdn.net/Touale/article/details/112546623