記事のディレクトリ
複雑さの分析
Big O時間計算量の表現:数式の低次、定数、および係数は成長傾向に影響を与えないため、すべて無視できます。最大の大きさを記録するだけで済みます。
時間計算量分析:
1。ループ実行時間が最も
長いコードのみに焦点を当てます2.追加ルール:合計の複雑さは最大の大きさのコードの複雑さに等しい
3.乗算ルール:ネストされたコードの複雑さは等しい巣の内側と外側へコードの複雑さの産物
いくつかの一般的な時間計算量の例の分析
多項式の大きさ
非多項式の大きさ、NP問題O(2n)およびO(n!)は非常に非効率的です
いくつかの一般的な多項式時間計算量
O(1):ループ、再帰はありません
O(logn)、O(nlogn):次のコード
i=1;
while (i <= n) {
i = i * 2;
}
変数iの値は等比数列です
i=1;
while (i <= n) {
i = i * 3;
}
コードの時間計算量がO(logn)であり、ループ内でn回実行する場合、時間計算量はO(nlogn)です。さらに、O(nlogn)も非常に一般的なアルゴリズムの時間計算量です。たとえば、マージソートとクイックソートの時間計算量はどちらもO(nlogn)です。
O(m + n)、O(m * n):
int cal(int m, int n) {
int sum_1 = 0;
int i = 1;
for (; i < m; ++i) {
sum_1 = sum_1 + i;
}
int sum_2 = 0;
int j = 1;
for (; j < n; ++j) {
sum_2 = sum_2 + j;
}
return sum_1 + sum_2;
}
mとnは2つのデータサイズを表します。mとnのどちらの大きさが大きいかを事前に評価することはできないため、複雑さを表現するときに、単純に加算の規則を使用して、そのうちの1つを省略することはできません。したがって、上記のコードの時間計算量はO(m + n)です。
スペースの複雑さの分析:スペースの割り当てのサイズを確認するだけで済みます。一般的なスペースの複雑さはO(1)、O(n)、O(n2)です。
要約の
複雑さは、時間の複雑さや空間の複雑さなど、プログレッシブの複雑さとも呼ばれます。アルゴリズムの実行効率とデータサイズの増大関係を分析するために使用されます。アルゴリズムの複雑さが高いほど、実行効率は低くなると大まかに表現できます。 。。一般的な複雑さは、低次から高次までそれほど多くありません:O(1)、O(logn)、O(n)、O(nlogn)、O(n2)。
最良、最悪の時間計算量、平均時間計算量
ケース1:
// n表示数组array的长度
int find(int[] array, int n, int x) {
int i = 0;
int pos = -1;
for (; i < n; ++i) {
if (array[i] == x) pos = i;
}
return pos;
}
時間計算量はO(n)
case2です。
// n表示数组array的长度
int find(int[] array, int n, int x) {
int i = 0;
int pos = -1;
for (; i < n; ++i) {
if (array[i] == x) {
pos = i;
break;
}
}
return pos;
}
時間計算量には多くの可能性があります。
最良:O(1)
最悪:O(n)
それで、平均は何ですか?
配列内のxの位置には、n + 1の場合があります。配列内ではなく配列の0-n-1の位置で、
それぞれの場合にトラバースする必要のある要素の数を合計してから、 n +1で割ると、トラバースする必要のある要素
の数の平均時間計算量を取得できます。大きなO表記では、係数、低次、定数を省略できます。したがって、式を単純化した後、ここで、得られる平均時間は複雑
です。次数はO(n)OKです。xが配列に現れる確率と配列の外側にある確率がそれぞれ1/2であると仮定すると、確率係数を考慮に入れます。式は
この値になります。これは確率理論の加重平均であり、期待値とも呼ばれます。したがって、平均時間計算量のフルネームは加重平均時間計算量または予想時間計算量と呼ばれる必要があります。
ただし、このコードの加重平均計算量は次のとおりです。続いている)
償却時間の複雑さ
操作間には一貫したタイミング関係があるため、次のように、時間の複雑さが高い他の操作に、複雑さが低い他の操作に時間を分散します。
// array表示一个长度为n的数组
// 代码中的array.length就等于n
int[] array = new int[n];
int count = 0;
void insert(int val) {
if (count == array.length) {
int sum = 0;
for (int i = 0; i < array.length; ++i) {
sum = sum + array[i];
}
array[0] = sum;
count = 1;
}
array[count] = val;
++count;
}
このコードは、データを配列に挿入する関数を実装しています。配列がいっぱいの場合、つまりコードでcount == array.lengthの場合、forループを使用して配列をトラバースして配列をクリアし、合計の後に合計値を配列の最初の位置に配置します。次に、新しいデータを挿入します。ただし、配列の先頭に空き領域がある場合は、データを配列に直接挿入します。
配列がクリアされるたびに(時間のかかるO(n))、次のn-1は時間O(1)を要し、時間のかかる高い時間を低い時間に償却し、平均償却複雑度はO(1)です
リファレンスコース:オタク時代の王鄭氏による「データ構造とアルゴリズムの美しさ」