web-dev-qa-db-ja.com

「Big O」表記のわかりやすい英語の説明は何ですか?

できるだけ正式な定義と単純な数学をお勧めします。

4744
Arec Barrwin

クイックノート、これはほぼ間違いなく Big O記法 (上限)とTheta記法(両側)の混同です。私の経験では、これは実際には学術以外の場面での議論の典型です。混乱を招きました。


このグラフで、複雑さを視覚化することができます。

Big O Analysis

私がBig-O記法に与えることができる最も簡単な定義はこれです:

Big-O表記は、アルゴリズムの複雑さを相対的に表したものです。

その文にはいくつかの重要で故意に選ばれた言葉があります。

  • relative:あなたはりんごとりんごを比較することしかできません。整数のリストをソートするアルゴリズムと算術乗算をするアルゴリズムを比較することはできません。加えて)意味のあることをあなたに言うでしょう。
  • Representation:Big-O(最も単純な形式で)は、アルゴリズム間の比較を単一の変数に減らします。この変数は、観測値または仮定に基づいて選択されます。しかし、比較は安価ですがスワッピングが高価な場合はどうなるでしょうか。
  • 複雑さ:10,000個の要素をソートするのに1秒かかり、100万個のソートにかかる時間はどれくらいですか?この場合の複雑さは、他の要素に対する相対的な尺度です。

あなたが残りを読んだときに戻ってきて上のことをもう一度読んでください。

私が考えることができるBig-Oの最もよい例は算術をすることです。 2つの番号を取ります(123456と789012)。私たちが学校で学んだ基本的な算術演算は次のとおりです。

  • 添加;
  • 引き算
  • 乗算;そして
  • 分割。

これらはそれぞれ操作または問題です。これらを解く方法をalgorithm)と呼びます。

加算は最も簡単です。数字を(右に)並べて、結果にその追加の最後の数字を書いている列に数字を追加します。その数の「十」の部分は次の列に持ち越されます。

このアルゴリズムでは、これらの数の加算が最も高価な演算であるとしましょう。これら2つの数字を足し合わせるには、6桁を足し合わせる必要があります(そしておそらく7番目の数字を付けなければなりません)。 2つの100桁の数字を一緒に追加すると、100回の加算が必要になります。 two10,000桁の数字を追加すると、10,000加算する必要があります。

パターンを見ますか? 複雑度(演算数)は、大きい方の桁数nに正比例します。これをO(n)と呼びます。または線形計算量

減算は似ています(キャリーではなく借りる必要があるかもしれません)。

掛け算は違います。あなたは数字を並べる、一番下の数字の最初の数字を取り、一番上の数字の各数字に対して順番にそれを乗算していきます。だから私たちの2つの6桁の数を乗算するために私達は36の乗算をしなければならない。最終結果を得るためにも、10または11列追加する必要があるかもしれません。

2つの100桁の数字がある場合は、10,000回の乗算と200回の加算を行う必要があります。 2つの100万桁の数字に対して、1兆を実行する必要があります(1012年掛け算と200万が足します。

アルゴリズムがn -2乗でスケーリングすると、これはO(n)2または2次複雑度)これは、もう1つの重要な概念を紹介する良い機会です。

複雑さのうち最も重要な部分だけを気にしています。

鋭いことに、操作の数を次のように表現できることに気づいたかもしれません。2 + 2n。しかし、2桁の100万桁を一例としたこの例からわかるように、2番目の項(2n)は重要ではなくなります(その段階での操作全体の0.0002%を占める)。

ここで最悪のシナリオを想定したことに気付くでしょう。一方が4桁でもう一方が6桁の場合、6桁の数を乗算すると、乗算は24回になります。それでも、その「n」、つまり両方が6桁の数字の場合の最悪のシナリオを計算します。したがって、Big-O表記は、アルゴリズムの最悪のシナリオについてのものです。

電話帳

私が考えることができる次の最良の例は通常ホワイトページまたは類似物と呼ばれる電話帳ですが、それは国によって異なります。しかし、私は姓、それからイニシャルまたはファーストネーム、おそらく住所、そして電話番号の順に人々をリストするものについて話しています。

1,000,000の名前が含まれている電話帳で「John Smith」の電話番号を検索するようにコンピュータに指示しているとしたら、どうしますか。あなたがSの開始のどのくらい遠くまで推測できるという事実を無視して(あなたができないと仮定しましょう)、あなたは何をしますか?

典型的な実装は、中央まで開いて、50万を取ることです。番目 それを "Smith"と比較してください。それが「スミス、ジョン」であるならば、私たちは本当にラッキーになりました。もっと可能性が高いのは、 "John Smith"がその名前の前後になるということです。それが終わったら、電話帳の後半を半分にして繰り返します。それが前の場合は、電話帳の前半を半分に分割して繰り返します。等々。

これは二分探索)と呼ばれ、あなたがそれを理解しているかどうかにかかわらず、プログラミングで毎日使用されています。

あなたが100万人の名前の電話帳で名前を見つけたいなら、あなたは実際に多くても20回これをすることによってどんな名前でも見つけることができます。検索アルゴリズムを比較する際に、この比較が私たちの 'n'であると判断します。

  • 3つの名前の電話帳の場合、2回の比較が必要です(最大で)。
  • 7のためにそれは多くとも3かかります。
  • 15の場合は4かかります。
  • 100万人のためにそれは20かかります。

それは驚くほどいいですね。

Big-Oの用語では、これはO(log n)または対数複雑度)になります。これで、問題の対数はln(基数e)、logになります。10年、ログ2 または他の基盤。 O(2n)と同じように、まだO(log n)でも構いません。2)とO(100n)2)両方ともO(n)2).

この時点で、Big Oを使用して3つのケースをアルゴリズムで決定できることを説明することは価値があります。

  • ベストケース:電話帳検索では、1回の比較で名前が見つかります。これはO(1)または定数複雑度;です。
  • 予想されるケース:上記のように、これはO(log n)です。
  • 最悪の場合:これもO(log n)です。

通常、私たちは最善のケースを気にしません。予想される最悪のケースに興味があります。時々これらのどちらかがもっと重要になるでしょう。

電話帳に戻ります。

電話番号を持っていて名前を見つけたい場合はどうしますか?警察は逆の電話帳を持っていますが、そのような検索は一般大衆には否定されています。それとも彼らですか?技術的には、通常の電話帳で番号を逆引きすることができます。どうやって?

あなたは姓から始めて番号を比較します。それが試合なら、素晴らしい、そうでなければ、あなたは次へ進む。電話帳は順不同(とにかく電話番号による)なので、このようにしなければなりません。

電話番号を指定して名前を探すには(逆引き):

  • ベストケース:O(1);
  • 予想されるケース:O(n)(500,000の場合);そして
  • 最悪の場合:O(n)(1,000,000の場合)。

巡回セールスマン

これは、コンピュータサイエンスにおける非常に有名な問題であり、言及に値する。この問題であなたはNの町を持っています。それらの町のそれぞれは、一定の距離の道路によって1つ以上の他の町にリンクされています。巡回セールスマン問題はすべての町を訪問する最短ツアーを見つけることです。

簡単に聞こえますか?もう一度考えてみて。

あなたがすべてのペアの間に道路がある3つの町A、B、Cがあるなら、あなたは行くことができます:

  • A→B→C
  • A→C→B
  • B→C→A
  • B→A→C
  • C→A→B
  • C→B→A

実際にはそれよりも少ないものがあります。これらのいくつかは同等であるからです(A→B→CとC→B→Aは同等です。たとえば、同じ道路を使用しているため、まったく逆です)。

実際には3つの可能性があります。

  • これを4つの町に持っていくと、12の可能性があります。
  • 5では60です。
  • 6は360になります。

これはfactorial)と呼ばれる数学演算の関数です。

  • 5! = 5×4×3×2×1 = 120
  • 6! = 6×5×4×3×2×1 = 720
  • 7! = 7×6×5×4×3×2×1 = 5040
  • 25! = 25×24×…×2×1 = 15,511,210,043,330,985,984,000,000
  • 50! = 50×49×…×2×1 = 3.04140932×1064

したがって、巡回セールスマン問題のBig-Oは、O(n!)または階乗または組み合わせの複雑さ)です。

あなたが200の町にたどり着くまでに、宇宙には伝統的なコンピューターの問題を解決するのに十分な時間が残っていません。

何か考えることがあります。

多項式時間

私がすぐに言及したかったもう一つのポイントはO(n)の複雑さを持つどんなアルゴリズムでもあるということですある多項式複雑度)を持つと言われるか、多項式時間)で解くことができます。

O(n)、O(n)2などはすべて多項式時間です。多項式時間では解決できない問題もあります。このため、世界では特定のものが使われています。公開鍵暗号はその代表的な例です。非常に大きな数の2つの素因数を見つけることは計算上困難です。そうでなかったら、私達は私達が使用する公開鍵システムを使用できなかった。

とにかく、それはBig O(改訂版)の私の(うまくいけば平易な英語の)説明のためのものです。

6317
cletus

アルゴリズムがどのように拡張するかを示します。 

O(n2二次複雑度として知られる)

  • 1アイテム:1秒
  • 10項目:100秒
  • 100アイテム:10000秒

アイテムの数は10倍に増えますが、時間は10倍に増えます。2。基本的に、n = 10でO(n2)倍率nを与える2 10です2

O(n)線形複雑度と呼ばれる)

  • 1アイテム:1秒 
  • 10アイテム:10秒
  • 100アイテム:100秒

今度はアイテムの数が10倍に増え、時間も増えます。 n = 10なので、O(n)の倍率は10です。

O(1)定数の複雑さとして知られる)

  • 1アイテム:1秒
  • 10アイテム:1秒
  • 100アイテム:1秒

項目数はまだ10倍に増えていますが、O(1)のスケーリング係数は常に1です。

O(log n)対数複雑度として知られる)

  • 1アイテム:1秒
  • 10アイテム:2秒
  • 100アイテム:3秒
  • 1000アイテム:4秒
  • 10000アイテム:5秒

計算数は、入力値の対数によってのみ増加します。そのため、この場合、各計算に1秒かかると仮定すると、入力nの対数が必要な時間、つまりlog nとなります。

それがその要旨です。それは正確にnではないかもしれないようにそれらは数学を減らします2 それとも彼らが言うことは何でも、それはスケーリングの支配的な要素になるでしょう。

686
Ray Hidayat

編集:クイックノート、これはほとんど間違いなく混乱します Big O表記 (これは上限です)とTheta表記(上限と下限の両方)です。私の経験では、これは実際には非学術的な設定での議論の典型です。混乱をおかけして申し訳ありません。

一文で:あなたの仕事の規模が大きくなると、それを完了するのにどれくらい時間がかかりますか?

明らかに、入力として「サイズ」を使用し、出力として「所要時間」を使用しているだけです。メモリ使用量などについて話したい場合も同じ考えが適用されます.

乾燥させたいTシャツがN個ある例です。 と仮定します乾燥位置に置くのは非常に迅速です(つまり、人間の相互作用は無視できます)。もちろん、実際にはそうではありません...

  • 外で洗濯ラインを使用:無限に大きな裏庭があると仮定すると、洗濯はO(1)時間で乾燥します。どれだけ持っていても、同じ太陽と新鮮な空気が得られるので、サイズは乾燥時間に影響しません。

  • 回転式乾燥機の使用:各荷物に10枚のシャツを入れ、1時間後にシャツを完成させます。 (ここでの実際の数字は無視してください。関係ありません。)したがって、50枚のシャツを乾燥させるには、10枚のシャツを乾燥させるのに5倍かかります。

  • すべてを通気性のある食器棚に入れる:すべてを1つの大きなパイルに入れて、一般的な暖かさをそのままにすると、中間のシャツが乾くまでに時間がかかります。詳細を推測したくはありませんが、これは少なくともO(N ^ 2)であると思われます。洗浄負荷を増やすと、乾燥時間が速くなります。

「ビッグO」表記法の1つの重要な側面は、指定されたサイズに対してどのアルゴリズムが高速になるかをしないということです。ハッシュテーブル(文字列キー、整数値)とペアの配列(文字列、整数)を比較します。文字列に基づいて、ハッシュテーブル内のキーまたは配列内の要素を見つける方が速いですか? (つまり、配列の場合、「文字列部分が指定されたキーと一致する最初の要素を見つけます。」)ハッシュテーブルは通常償却されます(〜=「平均」)O(1) —一度設定されると、 100エントリテーブルのエントリを見つけるのに、1,000,000エントリテーブルの場合とほぼ同じ時間がかかります。 (インデックスではなくコンテンツに基づいて)配列内の要素を見つけることは線形です。つまり、O(N) —平均では、エントリの半分を見る必要があります。

これにより、ルックアップ用の配列よりもハッシュテーブルが速くなりますか?必ずしも。エントリのコレクションが非常に小さい場合、配列の方が高速になる可能性があります。探しているもののハッシュコードを計算するのにかかる時間内にすべての文字列をチェックできる場合があります。ただし、データセットが大きくなると、ハッシュテーブルが最終的に配列に勝ちます。

241
Jon Skeet

Big Oは、入力が大きくなったときの、プログラムの実行時など、関数の成長動作の上限を表します。

例:

  • O(n):入力サイズを2倍にするとランタイムは2倍になります

  • 2):入力サイズが実行時の4倍になった場合

  • O(log n):入力サイズが倍になるとランタイムが1倍になります。

  • O(2n):入力サイズが1増加すると、ランタイムは2倍になります。

入力サイズは通常、入力を表すのに必要なビット単位のスペースです。

121
starblue

ビッグO表記法は、入力セットのサイズの関数として表される計算(アルゴリズム)が完了するのにかかる時間のおおよその尺度として、プログラマーによって最も一般的に使用されます。

Big Oは、入力数が増加したときに2つのアルゴリズムがどれだけうまくスケールアップするかを比較するのに役立ちます。

より正確には Big O表記 を使用して、関数の漸近的な動作を表現します。つまり、関数は無限に近づくにつれてどのように動作するかを意味します。

多くの場合、アルゴリズムの「O」は次のいずれかの場合に該当します。

  • O(1)-入力セットのサイズに関係なく、完了するまでの時間は同じです。例は、インデックスによる配列要素へのアクセスです。
  • O(Log N)-完了するまでの時間は、おおよそlog2(n)に沿って増加します。たとえば、Log2(1024)= 10およびLog2(32)= 5であるため、1024アイテムは32アイテムの約2倍の時間がかかります。例は、 バイナリ検索ツリー ( BST)。
  • O(N)-入力セットのサイズに比例してスケーリングする完了時間。つまり、入力セットのアイテム数を2倍にすると、アルゴリズムの所要時間は約2倍になります。例として、リンクリスト内のアイテムの数を数えます。
  • O(N Log N)-アイテム数にLog2(N)の結果を掛けたものが完了するまでの時間が長くなります。この例は、 heap sort および quick sort です。
  • O(N ^ 2)-完了するまでの時間は、アイテム数の2乗にほぼ等しくなります。この例は、 bubble sort です。
  • O(N!)-完了までの時間は、入力セットの階乗です。この例は、 巡回セールスマン問題ブルートフォースソリューション です。

Big Oは、入力サイズが無限大に向かって増加するときに、関数の成長曲線に意味のある方法で寄与しない要因を無視します。これは、関数に追加または乗算される定数が単に無視されることを意味します。

102
cdiggins

Big Oは、「自分のコードを実行するのに必要な時間とスペースの量」という一般的な方法で自分自身を「表現する」ための手段です。

よくO(n)、O(n)と表示されることがあります。2)、O(nlogn)など、これらすべては表示するための単なる方法です。アルゴリズムはどのように変わりますか?

O(n)はBig Oがnであることを意味します。そして今、あなたは "What is n!?"と思うかもしれません。まあ "n"は元素の量です。配列内の項目を検索したいイメージング。各要素を調べて、「あなたは正しい要素/項目ですか?」と表示する必要があります。最悪の場合、項目は最後のインデックスにあります。これは、リストに項目があるのと同じくらいの時間がかかったことを意味します。 。

だから、あなたは理解しているかもしれません "n2「つまり、さらに具体的に言うと、単純で最も単純なソートアルゴリズム、bubblesortを使用するという考えを試してください。このアルゴリズムでは、各項目についてリスト全体を見る必要があります。

私のリスト

  1. 1
  2. 6
  3. 3

ここでの流れは以下のようになります。

  • 1と6を比較すると、どれが一番大きいですか? Ok 6は正しい位置にあり、前進しています。
  • 6と3を比較して、おお、3はもっと少ないです! Okリストが変更されたので、ここから始めましょう。

これはO n2 なぜなら、あなたはリスト中のすべての項目を見る必要があるからです。各項目について、もう一度比較するために、すべての項目を見ます。これは「n」でもあるため、すべての項目について、n * n = nという意味になります。2

私はこれがあなたがそれを望むのと同じくらい簡単であることを願っています。

しかし、覚えておいて、ビッグOは時間と空間の方法で自分自身を磨くための単なる方法です。

78
Filip Ekberg

Big Oは、アルゴリズムの基本的なスケーリングの性質を表します。

Big Oが与えられたアルゴリズムについてあなたに伝えない多くの情報があります。それは骨を切り開き、アルゴリズムのスケーリングの性質、特にアルゴリズムのリソース使用(思考時間またはメモリ)が「入力サイズ」に応じてどのようにスケーリングするかについての情報のみを与えます。

蒸気機関とロケットの違いを考えてください。プリウスエンジンとランボルギーニエンジンのように、種類が異なるだけではありませんが、本質的には劇的に異なる種類の推進システムです。 Steamエンジンはおもちゃのロケットよりも速いかもしれませんが、Steamピストンエンジンは軌道上のロケットの速度を達成することはできません。これは、これらのシステムが、所与の速度(「入力サイズ」)に達するために必要な燃料の関係(「リソース使用量」)に関して異なるスケーリング特性を有するためである。

これはなぜそれほど重要なのでしょうか。ソフトウェアは、最大で1兆までの要因によってサイズが異なる可能性がある問題を処理するためです。しばらく考えてみてください。月への移動に必要な速度と人間の歩行速度の比は10,000:1未満であり、ソフトウェアが直面する可能性がある入力サイズの範囲と比較してそれは絶対に小さいです。そしてソフトウェアは入力サイズの天文学的な範囲に直面するかもしれないので、アルゴリズムのBig Oの複雑さの可能性がある、それはどんな実装の詳細をも切り捨てることの基本的なスケーリングの性質です。

標準的なソートの例を考えてください。バブルソートはO(n2)merge-sortがO(n log n)の間。バブルソートを使用するアプリケーションAとマージソートを使用するアプリケーションBの2つのソートアプリケーションがあるとします。入力サイズが約30要素の場合、アプリケーションAはソート時のアプリケーションBより1,000倍高速です。 30を超える要素を並べ替える必要がまったくない場合は、これらの入力サイズでははるかに高速であるため、アプリケーションAを選択する必要があります。ただし、1000万項目をソートする必要があると思われる場合は、アプリケーションBが実際にはアプリケーションAよりも数千倍高速になってしまうことが予想されます。これは、各アルゴリズムのスケーリング方法によるものです。

53
Wedge

これは、Big-Oの一般的な種類を説明するときに使用する傾向がある、わかりやすい英語のお姉さんです。

すべての場合において、リストの上にあるものよりリストの上にあるものを優先してください。ただし、より複雑なクラスに移行するためのコストは大きく異なります。

O(1):

成長無し。問題の大きさに関係なく、同じ時間で解決できます。これは、放送範囲内にいる人の数に関係なく、一定の距離で放送するのに同量のエネルギーがかかる放送にやや似ています。

O(log n ):

この複雑さは O(1) と同じですが、少しだけ悪いという点が異なります。すべての実用的な目的のために、あなたはこれを非常に大きな一定のスケーリングとして考えることができます。 1,000個から10億個のアイテムを処理する作業の違いは、わずか6倍です。

O( n ):

問題を解決するためのコストは、問題のサイズに比例します。問題が2倍になると、ソリューションのコストは2倍になります。データ入力、ディスク読み取り、ネットワークトラフィックなど、ほとんどの問題は何らかの方法でコンピュータにスキャンインする必要があるため、これは一般的に手ごろな倍率です。

O( n log n ):

この複雑さは O( n と非常によく似ています。すべての実用的な目的のために、2つは同等です。このレベルの複雑さは、一般的にまだスケーラブルと見なされます。仮定を微調整することによって、いくつかの O( n log n アルゴリズムを O( n アルゴリズムに変換できます。例えば、キーのサイズを制限すると、 O( n log n から O( n へのソートが少なくなります。

O( n 2):

正方形として成長します。ここで、 n は正方形の一辺の長さです。これは、ネットワーク内の全員がネットワーク内の他の全員を知っている可能性がある「ネットワーク効果」と同じ成長率です。成長は高価です。ほとんどのスケーラブルなソリューションは、重要な体操をしないとこのレベルの複雑さを持つアルゴリズムを使用できません。これは一般に他のすべての多項式の複雑さに適用されます - O( n k - 同様に。

O(2 n ):

拡大縮小しません。あなたは、どんな小さな問題でも解決する見込みはありません。何を避けるべきかを知るため、および専門家が O( n )にある近似アルゴリズムを見つけるのに役立ちます。k

37
Andrew Prock

Big Oは、アルゴリズムがその入力のサイズに対してどれだけの時間/スペースを使用するかの尺度です。 

アルゴリズムがO(n)の場合、時間/空間はその入力と同じ割合で増加します。

アルゴリズムがO(nの場合2それから時間/空間はその入力の2乗の割合で増加します。

等々。

35
Brownie

ソフトウェアプログラムの速度を測定することは非常に困難です、そして試みるとき、答えは非常に複雑で、例外と特別な場合でいっぱいになることができます。これは大きな問題です。なぜなら、2つの異なるプログラムを互いに比較してどちらが「最速」であるかを調べたい場合、これらの例外や特別なケースはすべて邪魔になり、役に立たないからです。

このようなすべての不都合な複雑さの結果として、人々は可能な限り小さく、最も複雑でない(数学的)表現を使用してソフトウェアプログラムの速度を記述しようとします。これらの表現は非常に粗雑な近似です。ただし、幸運にも、それらはソフトウェアが速いか遅いかの「本質」を捉えます。

それらは近似値なので、私たちは表現に "O"(Big Oh)という文字を使用しています。これは、読者に大きな単純化をしていることを知らせるための規則です。 (そして、その表現がいかなる意味においても正確であると誤って誰も考えていないことを確認するため)。

あなたが「おお」を「または「およそ」のオーダーで」という意味で読んだとしても、あなたはそれほど遠くに間違って行くことはないでしょう。 (私はBig-Ohの選択はユーモアの試みだったかもしれないと思います)。

これらの "Big-Oh"表現がやろうとしている唯一のことは、ソフトウェアが処理しなければならないデータ量を増やすにつれてソフトウェアがどれだけ遅くなるかを記述することです。処理する必要があるデータ量を2倍にした場合、ソフトウェアは作業を完了するのに2倍の時間が必要ですか? 10倍の長さ?実際には、遭遇して心配する必要がある非常に限られた数のbig-Oh式があります。

いいもの:

  • O(1) 定数 :入力がいくら大きくてもプログラムは実行に同じ時間がかかります。
  • O(log n) 対数 :入力のサイズが大きく増加しても、プログラムの実行時間はゆっくりと増加します。

悪い人:

  • O(n) Linear :プログラムの実行時間は入力のサイズに比例して増加します。
  • O(n^k) 多項式 : - 入力のサイズが大きくなるにつれて、多項式関数として処理時間はますます速くなります。

...そして醜い:

  • O(k^n) 指数関数 プログラムの実行時間は、問題のサイズが少しでも大きくなっても非常に速く増加します - 指数関数的アルゴリズムで小さなデータセットを処理することは現実的です。
  • O(n!) Factorial プログラムの実行時間は、ごくわずかで些細なように思われるデータセット以外は待つことができないほど長くなります。
31
William Payne

Big Oのわかりやすい英語の説明は何ですか?できるだけ少ない正式な定義と簡単な数学で。

平易な英語の説明 の必要性 Big-O表記の場合:

私たちがプログラムするとき、私たちは問題を解決しようとしています。私たちがコーディングしたものはアルゴリズムと呼ばれます。 Big O記法を使用すると、標準化された方法でアルゴリズムの最悪の場合のパフォーマンスを比較できます。ハードウェアの仕様は時間とともに変化し、ハードウェアの改良はアルゴリズムの実行にかかる時間を短縮することができます。しかし、ハードウェアを交換しても、アルゴリズムが同じであるため、時間の経過とともにアルゴリズムが改善されたり改善されたりするわけではありません。したがって、異なるアルゴリズムを比較して、どちらが優れているかどうかを判断するために、Big O表記を使用します。

平易な英語の説明 何を Big O表記は:

すべてのアルゴリズムが同じ時間内に実行されるわけではなく、入力内の項目数に基づいて変化する可能性があります。これを n と呼びます。これに基づいて、 n が大きくなるにつれて、最悪の場合の分析、つまり実行時間の上限を考慮します。多くのBig O記法がそれを参照しているので、 n が何であるかを知っておく必要があります。

31
James Oravec

簡単な答えは、次のとおりです。

大きいOはそのアルゴリズムのための最悪の可能な時間/スペースを表します。アルゴリズムは、その制限を超えてそれ以上のスペース/時間を費やすことはありません。極端な場合、大きいOは時間/空間の複雑さを表します。

27
AlienOnEarth

わかりました、私の2才。

Big-Oは、 増加率 /プログラムによって消費されるリソースのw.r.tです。問題インスタンスサイズ

リソース:合計CPU時間、最大RAM領域になります。デフォルトではCPU時間を表します。

問題が「合計を探す」であるとします。 

int Sum(int*arr,int size){
      int sum=0;
      while(size-->0) 
         sum+=arr[size]; 

      return sum;
}

problem-instance = {5,10,15} ==> problem-instance-size = 3、繰り返し回数= 3

problem-instance = {5,10,15,20,25} ==> problem-instance-size = 5繰り返し回数= 5

サイズ "n"の入力の場合、プログラムは配列内で "n"回の繰り返しの速度で成長しています。したがって、Big-OはO(n)で表されるNです。

問題が「組み合わせを見つける」であるとします。 

    void Combination(int*arr,int size)
    { int outer=size,inner=size;
      while(outer -->0) {
        inner=size;
        while(inner -->0)
          cout<<arr[outer]<<"-"<<arr[inner]<<endl;
      }
    }

problem-instance = {5,10,15} ==> problem-instance-size = 3、total-iterations = 3 * 3 = 9

problem-instance = {5,10,15,20,25} ==> problem-instance-size = 5、total-iterations = 5 * 5 = 25

サイズ "n"の入力では、プログラムは配列内で "n * n"回の繰り返しの速度で成長しています。したがって、Big-OはNです。2 O(nと表します。2

27
Ajeet Ganga

Big O表記は、スペースまたは実行時間の観点からアルゴリズムの上限を表す方法です。 nは問題の要素数(配列のサイズ、ツリー内のノード数など)です。nが大きくなるにつれて実行時間を記述することに興味があります。

あるアルゴリズムがO(f(n))であると言うとき、そのアルゴリズムによる実行時間(または必要なスペース)は常にある一定の時間f(n)より短いということです。

二分検索の実行時間がO(logn)であるということは、log(n)を掛けることができる定数cが存在するということです。二分検索の実行時間よりも常に長くなります。 。この場合、log(n)の比較には常に一定の係数があります。

言い換えれば、g(n)がアルゴリズムの実行時間である場合、g(n) = O(f(n))のようになります。 g(n) <= c * f(n)n> kのとき、cとkは定数です。

24
John C Earls

"Big Oの簡単な英語の説明とは何ですか?できるだけ正式な定義が少なく、単純な数学です。"

このように美しくシンプルで短い質問は、少なくとも生徒が個別指導中に受けるような短い回答に値すると思われます。

Big O表記は、入力データの量のみ **に関して、アルゴリズムがどれだけの時間*内で実行できるかを単に示します。

(*素晴らしい、nit-free時間の感覚で!)
(**重要なのは、人々が alwaysもっと欲しい 、今日か明日かを問わず)

さて、ビッグO表記法の素晴らしいところは、それが何をするのかということです。

  • 実際には、Big O分析はとても便利で重要です。BigOは、アルゴリズムの焦点を真っ直ぐに重視しているためですown複雑さと完全にignores JavaScriptエンジン、CPUの速度、インターネット接続など、モデルと同じくらいすぐに時代遅れになりそうなものすべてのように、単なる比例定数ですT。 Big Oは、現在または未来に生きる人々にとって等しく重要な方法でのみパフォーマンスに焦点を合わせます。

  • Big O表記法は、コンピュータープログラミング/エンジニアリングの最も重要な原則に直接スポットライトを当てます。これは、優れたプログラマー全員に思考と夢を持ち続けるよう促すものです。技術の遅い前進を超えて結果を達成する唯一の方法はより良いアルゴリズムを発明する

23
Joseph Myers

アルゴリズム例(Java):

// given a list of integers L, and an integer K
public boolean simple_search(List<Integer> L, Integer K)
{
    // for each integer i in list L
    for (Integer i : L)
    {
        // if i is equal to K
        if (i == K)
        {
            return true;
        }
    }

    return false;
}

アルゴリズムの説明:

  • このアルゴリズムは、キーを探しながら、項目ごとにリストを検索します。

  • リストの各項目を繰り返します。それがキーの場合はTrueを返します。

  • キーが見つからずにループが終了した場合は、Falseを返します。

Big-O表記は、複雑度(Time、Space、..)の上限を表します。

時間の複雑さについてBig-Oを見つけるには:

  • 最悪の場合(入力サイズに関して)にかかる時間を計算します。

  • 最悪の場合:キーはリストに存在しません。

  • 時間(ワーストケース)= 4n + 1

  • 時間:O(4n + 1)= O(n) | Big-Oでは、定数は無視されます

  • O(n)〜線形

ベストケースの複雑さを表すBig-Omegaもあります:

  • ベストケース:キーは最初の項目です。

  • 時間(ベストケース)= 4

  • 時間:Ω(4)= O(1)〜インスタント\定数

20
Khaled.K

Big O

f(x)= O(g(x))xがaになったとき(たとえば、a = +∞)は、関数があることを意味しますkそのようなもの:

  1. f(x)= k(x)g(x)

  2. kはaの近傍に制限されます(a = +∞の場合、これは、すべてのx> Nに対して、NとMが存在することを意味します|| k(x)| <M)。

言い換えれば、平易な英語では:f(x)= O(g(x))、x→aは、aの近傍にあることを意味しますfは、gと有界関数の積に分解されます。

小o

ところで、比較のために小さなoの定義を示します。

f(x)= o(g(x))xがに移動すると、次のような関数kがあることを意味します。

  1. f(x)= k(x)g(x)

  2. k(x)は、xがaになると0になります。

  • sin x = O(x)(x→0の場合).

  • sin x = O(1) when x→+∞、

  • バツ2 + x = O(x) x→0の場合、

  • バツ2 + x = O(x2)x→+∞の場合、

  • ln(x)= o(x) = O(x)ときx→+∞。

注意!等号「=」の表記は「偽の等式」を使用します:o(g(x)) = O(g(x))、ただしO(g(x)) = o(g(x))の場合はfalse。同様に、「x→+∞」の場合、「ln(x)= o(x)」と書くことはできますが、式「o(x)= ln(x)」は意味がありません。

その他の例

  • O(1)= O(n) = O(n2)n→+∞(ただし、逆ではない場合、等式は「偽」です)、

  • O(n)+ O(n2)= O(n2)n→+∞の場合

  • O(O(n2))= O(n2)n→+∞の場合

  • 2)に3)= O(n5)n→+∞の場合


ウィキペディアの記事は次のとおりです。 https://en.wikipedia.org/wiki/Big_O_notation

18
Alexey

Big O記法は、任意の数の入力パラメータが与えられたときにアルゴリズムがどれだけ速く実行されるかを表す方法です。これを "n"と呼びます。異なるマシンは異なる速度で動作し、4.5 Ghzオクトコアプロセッサを搭載したシステムを実行している間は実行している可能性があるため、アルゴリズムに5秒かかると言ってもあまり意味がありません15歳の800MHzシステムで、アルゴリズムに関係なく時間がかかる可能性があります。そのため、アルゴリズムが時間的にどのくらい速く実行されるかを指定するのではなく、入力パラメータの数、つまり "n"に関して実行される速度を指定します。このようにアルゴリズムを記述することで、コンピュータ自体の速度を考慮に入れることなく、アルゴリズムの速度を比較することができます。

17
Brian

私はこの主題にさらに貢献しているかどうかわからないが、それでも私は共有しようと思っていた:私はかつて このブログ記事 Big Oに関するいくつかの非常に役立つ(非常に基本的な)説明と例を持っている: 

例を挙げれば、これは私のべっ甲のような頭蓋骨の基本を理解するのに役立ちました。そのため、正しい方向に進むためには10分ほど読むのがかなり下品だと思います。 

11
Priidu Neemre

あなたは大きなOを知るためにすべてがあることを知りたいですか?私もそうです。

それで、大きなOについて話すために、私はそれらの中でたった1拍の単語を使うつもりです。 Wordごとに1つの音。小さな言葉は速いです。あなたはこれらの言葉を知っています、そして私もそうします。私たちは一つの音で言葉を使います。彼らは小さい。私たちが使用するすべての単語をあなたが知っていると確信しています!

それでは、あなたと私が仕事について話しましょう。ほとんどの場合、私は仕事が好きではありません。あなたは仕事が好きですか?あなたがそうであるかもしれませんが、私はそうしないと確信しています。

私は仕事に行きたくない。私は仕事に時間を費やすのは好きではありません。自分のやり方ができたら、ただ遊んで楽しいことをやりたいです。あなたは私と同じように感じますか?

時々、私は仕事に行かなければなりません。悲しいですが、本当です。だから、私が仕事をしているとき、私はルールがあります:私はより少ない仕事をしようとします。私はできる限り仕事ができなくなりそうです。それから私は遊びに行きます!

だからここに大きなニュースがあります:大きなOは私が仕事をしないように手助けすることができます!大きなOを知っていれば、もっと時間をかけて遊べます。それが大きなOが私を助けるのです。

今私はいくつかの仕事をしています。私はこのリストを持っています:1、2、3、4、5、6。このリストにすべてのものを追加しなければなりません。 

うわー、私は仕事が嫌いです。しかし、まあ、私はこれをしなければなりません。だからここに行きます。

1プラス2は3…プラス3は6……4は…私は知らない。迷子になりました。私の頭の中でやるのは難しすぎる。私はこの種の仕事にあまり気をかけません。

だから仕事をしないでください。あなたと私だけでそれがどれほど難しいか考えてみましょう。 6つの数字を追加するには、どれだけの作業をしなければなりませんか?

それでは、見てみましょう。私は1と2を加え、それからそれを3に加え、それからそれを4に加えなければなりません。これを解決するには、6回追加する必要があります。

この数学がどれほど難しいかを教えてください。

Big Oは言う:これを解決するために6つの追加をしなければならない。 1から6までのそれぞれについて、1つを追加します。 6つの小さな作業...各作業は1つの追加です。

さて、私は今それらを追加するための作業をしません。しかし、私はそれがどれほど難しいかを知っています。それは6つの追加になります。

ああ、今、私はもっと仕事をしています。シーシー誰がこの種のものを作るのですか?

今、彼らは私に1から10まで追加するように頼みます!なぜそれをするのですか? 1〜6を追加したくありませんでした。 1から10まで追加するには…まあ…それはさらにもっと難しいでしょう!

それはどれほど難しいだろうか?あとどのくらいの作業が必要ですか。多かれ少なかれステップが必要ですか?

そうですね、私は10回の追加が必要だと思います。 10は6以上です。 1から6までではなく、1から10までを追加するには、もっと多くの作業が必要です。

今は追加したくありません。それを追加するのがどれほど難しいかを考えたいだけです。そして、できるだけ早くプレイしたいと思っています。

1から6まで追加するには、それはいくつかの仕事です。しかし、1から10まで追加すると、それはより多くの作業になりますか?

Big Oはあなたの友達で私のものです。大きいOは私達が私達がどれだけの仕事をしなければならないかについて考えるのを助けるので、私達は計画することができる。そして、もし私たちがOの大きい友達であれば、彼は私たちがそれほど難しいことではない仕事を選ぶ手助けをすることができます!

今、私たちは新しい仕事をしなければなりません。あらいやだ。私はこの仕事が全く好きではありません。

新しい仕事は、1からnまでのすべてのものを追加することです。

待つ! nは何ですか?私はそれが恋しいですか?あなたが私にnが何であるかを私に言わないならばどうすれば私は1からnまで追加できますか?

まあ、私はnが何であるかわからない。言わなかった。あなたでしたか?いいえ?しかたがない。だから私たちはその仕事をすることができません。うわー。

しかし、今はその作業を行いませんが、nがわかっていれば、それがどれほど難しいかを推測することができます。私たちはn個のものを合計しなければならないでしょうね。もちろん!

今ここに大きなOが来ます、そして彼は私達にこの仕事がどれほど難しいかを教えてくれるでしょう。彼は、次のように述べています。1からNまでのすべてのものを1つずつ追加するのはO(n)です。これらすべてを追加するには、[私はn回追加しなければならないことを知っています。] [1]これは大きなOです。彼は、ある種の仕事をするのがどれほど難しいかを教えてくれました。

私にとって、私は大きいOを大きくて遅い、上司の男のように思います。彼は仕事を考えていますが、それはしません。 「その仕事は早い」と言うかもしれません。あるいは、「あの仕事はとても遅くて難しい」と言うかもしれません。しかし、彼はその仕事をしません。彼はただその作品を見て、それからどれだけの時間がかかるかもしれないかを教えてくれます。

大きなOを気にかけています。私は仕事が好きではありません!誰も仕事が好きではありません。だからこそ私たちみんな大きなOが大好きです!彼は私たちにどれだけ早く仕事ができるかを話します。彼は私たちがどれほど大変な仕事であるかを考える手助けをしてくれます。

ええと、もっと仕事。今、仕事をしないでください。しかし、それを実行するための計画を立てましょう。

彼らは私達に10枚のカードのデッキをくれた。それらはすべて混同されています。7、4、2、6…まったくストレートではありません。そして今...私たちの仕事はそれらをソートすることです。

ええ。それは多くの仕事のようですね。

このデッキを並べ替えるにはどうすればよいですか。私は計画があります。

最初から最後まで、デッキを通してカードの各ペアをペアごとに見ていきます。あるペアの最初のカードが大きく、そのペアの次のカードが小さい場合、それらを交換します。そうでなければ、私は次のペアに進む、というようにして...そしてすぐに、デッキは完成です。

デッキが完成したら、私は尋ねます:そのパスでカードを交換しましたか?もしそうなら、私は上から、もう一度やり直さなければなりません。

ある時点で、ある時点で、スワップがなくなり、私たちの種類のデッキが実行されます。そんなに仕事!

さて、それらのルールでカードをソートするには、どれだけの作業が必要でしょうか。

私は10枚のカードを持っています。そして、たいていの場合、つまり私がたくさんの運を持っていないのであれば、デッキ全体で最大10回のカード交換を行いながら、デッキ全体を最大10回まで行わなければなりません。

おお、私を助けて!

Big Oが入ってくると言う:n枚のカードのデッキのために、このようにソートすることはO(Nの2乗)時間のうちに行われるだろう。

なぜ彼はnの2乗を言うのですか?

さて、あなたはnの2乗がn×nであることを知っています。今、私はそれを得ます:デッキを通してn回あるかもしれないものまでn個のカードをチェックしました。これは、それぞれnステップの2つのループです。これは、やるべきことが多くなったことです。確かにたくさんの仕事があります。

大きなOがO(n 2乗)の仕事になると言っても、鼻の上でn 2乗の加算を意味するわけではありません。場合によっては、少し小さいかもしれません。しかし、最悪の場合、デッキをソートする作業はnの2乗ステップ近くになります。

今ここに大きいOが私達の友人であるところです。

Big Oはこれを指摘しています。nが大きくなるにつれて、私たちがカードをソートするとき、その仕事は古いjust-these-things-things仕事よりもはるかに困難になります。これはどのようにしてわかりますか。

さて、もしnが本当に大きくなっても、nやnの2乗に何を足しても構いません。 

Nが大きい場合、nの2乗はnより大きくなります。

Big Oは、物事を並べ替えることは、物事を追加することよりも難しいことを教えてくれます。 nが大きい場合、O(nの2乗)はO(n)以上です。つまり、nが実際に大きくなった場合、n個の混合デッキを並べ替えるには、単にn個の混合ものを追加するよりも時間がかかる必要があります。

Big Oは私たちのために仕事を解決しません。 Big Oは、その作業がどれほど難しいかを教えてくれます。

私はカードのデッキを持っています。私はそれらを並べ替えました。お手伝いしました。ありがとう。

カードをソートするもっと速い方法はありますか?大きなOは私たちを助けることができる?

はい、もっと速い方法があります!それは学ぶのにいくらか時間がかかります、しかしそれは働きます...そしてそれはかなり速く働きます。あなたもそれを試すことができますが、各ステップであなたの時間をかけて、あなたの場所を失うことはありません。

デッキをソートするこの新しい方法では、しばらく前に行った方法でカードのペアをチェックしません。このデッキを並べ替えるための新しい規則は次のとおりです。

One:私たちが今取り組んでいるデッキの一部からカードを1枚選びます。あなたが好きならあなたは私のために一つを選ぶことができます。 (初めてこれを実行するとき、「今作業中のデッキの一部」は、もちろんデッキ全体です。)

2:あなたが選んだそのカードの上にデッキを広げます。この広がりは何ですか。どうやってスプレーするの?さて、私はスタートカードから1つずつ下に行き、そしてスプレイカードよりも高いカードを探します。

三つ目:私は最後のカードから上に行き、そしてスプレイカードよりも低いカードを探します。 

これら2枚のカードを見つけたら、それらを交換して、交換するカードを探します。つまり、私はステップ2に戻って、あなたがもう少し選んだカードにスプレーします。

ある時点で、このループ(2から3まで)は終了します。この検索の両半分がスプレイカードに出合った時点で終了します。それから、ステップ1で選んだカードでデッキを広げたところです。これで、スタート付近のすべてのカードは、スプレイカードよりも低くなりました。そして終わり近くのカードはスプレイカードより高いです。クールなトリック!

4つ(そしてこれは楽しい部分です):私は今2つの小さなデッキを持っています。1つはスプレイカードより低く、もう1つは高いです。今、私はそれぞれの小さなデッキで、ステップ1に行きます!つまり、最初の小さいデッキのステップ1から始め、その作業が終わったら、次の小さいデッキのステップ1から始めます。 

私はデッキをいくつかの部分に分割し、それぞれの部分をもっと小さく、もっと小さく並べ替える。今、これはすべてのルールで、遅く見えるかもしれません。しかし、私を信頼してください、それはまったく遅くありません。ソートする最初の方法よりもはるかに少ない作業です。

この種類は何と呼ばれますか?クイックソートと呼ばれます。そのソートは C. A. R. Hoare という人によって行われ、彼はそれをクイックソートと呼びました。これで、クイックソートが常に使用されるようになりました。

クイックソートは大きなデッキを小さなものに分割します。つまり、大きなタスクを小さなタスクに分割します。

うーん。そこにルールがあるかもしれない、と思います。大きなタスクを小さくするには、それらを分割します。

この種はとても速いです。どれくらい早く?大きなOは私たちに言っています:このような場合、この種のO(n log n)の作業が必要です。 

それは第一種よりも多かれ少なかれ速いですか?大O、助けてください!

最初のソートはO(n 2乗)でした。しかしクイックソートはO(n log n)です。あなたはn log nがnの2乗より小さいことを知っています。それで、クイックソートが高速であることがわかります。

あなたがデッキを並べ替える必要がある場合、最善の方法は何ですか?さて、あなたはあなたが望むことをすることができますが、私はクイックソートを選びます。

クイックソートを選択するのはなぜですか?私は仕事をするのは嫌いです、もちろん!仕事が終わったらすぐに仕事を終わらせたい。

クイックソートの方が作業が少ないことをどうやって知ることができますか?私はO(n log n)がO(n 2乗)より小さいことを知っています。 Oはもっと小さいので、クイックソートはあまり手間がかかりません。

今、あなたは私の友人、ビッグOを知っています。彼は私たちがより少ない仕事をするのを助けます。そして、あなたが大きいOを知っていれば、あなたはあまりにも少ない仕事をすることができます!

あなたは私と一緒にすべてのことを学びました!あなたはとても頭がいいです!どうもありがとうございます!

これで作業は完了しました。遊びに行きましょう。


[1]:1からnまでのすべてのものを一度にカンニングして追加する方法があります。ガウスという名前の子供の中には、8歳のときにこれを見つけた人もいます。私はそれほど賢くはありませんので、 彼がどうやったのか私に聞いてはいけません

11
johnwbyrd

アルゴリズムAについて話していると仮定します。これは、サイズnのデータセットで何かを行う必要があります。

O( <some expression X involving n> )は、簡単な英語では:

Aの実行時に不運な場合、完了するにはX(n)操作が必要になる場合があります。

それが起こると、特定の機能があります(それらはimplementationsof X(n))しばしば。これらはよく知られており、簡単に比較できます(例:1Log NNN^2N!など)

Aと他のアルゴリズムについて話すときにこれらを比較することにより、それらの操作の数に従ってアルゴリズムをランク付けすることは簡単ですmay(最悪の場合)完了する必要があります。

一般に、私たちの目標はアルゴリズムを見つけるか構造化することですA可能な限り低い数値を返す関数X(n)を持つように。

9
Kjartan

時間の複雑さを理解するためのもっと簡単な方法時間の複雑さを計算するための最も一般的な測定基準はBig O記法です。これにより、Nが無限大に近づくにつれてNに関連して実行時間を推定できるように、すべての定数係数が削除されます。一般的には、このように考えることができます:

statement;

一定です。ステートメントの実行時間は、Nに対して変化しません。

for ( i = 0; i < N; i++ )
  statement;

線形です。ループの実行時間はNに正比例します。Nが2倍になると、実行時間も2倍になります。

for ( i = 0; i < N; i++ ) 
{
for ( j = 0; j < N; j++ )
  statement;
}

二次です。 2つのループの実行時間はNの2乗に比例します。Nが2倍になると、実行時間はN * Nだけ増加します。

while ( low <= high ) 
{
 mid = ( low + high ) / 2;
 if ( target < list[mid] )
 high = mid - 1;
 else if ( target > list[mid] )
  low = mid + 1;
else break;
}

対数です。アルゴリズムの実行時間は、Nを2で割ることができる回数に比例します。これは、アルゴリズムが反復ごとに作業領域を半分に分割するためです。

void quicksort ( int list[], int left, int right )
{
  int pivot = partition ( list, left, right );
  quicksort ( list, left, pivot - 1 );
  quicksort ( list, pivot + 1, right );
}

N * log(N)です。実行時間は対数的なN個のループ(反復的または再帰的)で構成されているため、アルゴリズムは線形と対数の組み合わせです。

一般に、1次元のすべての項目を使って何かを行うことは線形であり、2次元のすべての項目を使って何かを行うことは2次であり、作業領域を半分に分割することは対数です。 3次、指数、平方根などの他のBig O測度がありますが、それらはほとんど一般的ではありません。 Big O表記はO()として表されます。ここで、はメジャーです。クイックソートアルゴリズムは、O(N * log(N))と記述されます。

注:これはどれも、最良、平均、および最悪の場合の尺度を考慮に入れていません。それぞれが独自のBig O表記を持ちます。これは非常に単純化した説明です。 Big Oが最も一般的ですが、私が示したものよりも複雑です。ビッグオメガ、リトルオ、ビッグシータなどの表記法もあります。あなたはおそらくそれらをアルゴリズム分析コースの外では遭遇しないでしょう。 

  • でもっと参照してください: ここ
9
nitin kumar

AmazonからHarry Potter:Complete 8-Film Collection [Blu-ray]を注文し、同時に同じフィルムコレクションをオンラインでダウンロードするとしましょう。どの方法が速いかをテストしたいと思います。配達は到着するのにほぼ1日かかり、ダウンロードは約30分早く完了しました。すばらしいです!だから、それはタイトなレースです。

ロード・オブ・ザ・リング、トワイライト、ダークナイトトリロジーなどのBlu-ray映画をいくつか注文して、それらすべての映画を同時にオンラインでダウンロードした場合はどうなりますか。今回は、配達は完了するのにまだ1日かかりますが、オンラインダウンロードが完了するまでに3日かかります。出力は一定です。これをO(1)と呼びます。

オンラインダウンロードの場合、ダウンロード時間はムービーファイルのサイズ(入力)に正比例します。これをO(n)と呼びます。

実験から、オンラインショッピングはオンラインダウンロードよりも優れていることがわかりました。アルゴリズムのスケーラビリティ効率を分析するのに役立つので、大きなO記法を理解することは非常に重要です。

注: Big O表記は、アルゴリズムの最悪のシナリオを表します。 O(1)およびO(n)が上記の例の最悪のシナリオであるとします。

参照http://carlcheo.com/compsci

9
raaz

あなたの頭の中に無限の適切な概念があるならば、それから非常に簡単な説明があります:

Big O表記は、無限大の問題を解決するためのコストを表します。

そしてさらに

定数係数は無視できる

アルゴリズムを2倍の速さで実行できるコンピュータにアップグレードした場合、大きなO表記はそれに気付かないでしょう。定数の改善は小さすぎて、大きなO表記が機能する規模では気付くことすらできません。これはbig O記法の設計の意図的な部分であることに注意してください。

ただし、定数よりも「大きい」ものは何でも検出できますが。

サイズが「無限大」と見なすのに十分なほど「大きい」計算を行うことに関心がある場合、大きいO表記は問題を解決するためのおおよそのコストです。


上記のことが意味を成さないのであれば、頭の中には互換性のある直感的な無限大の概念がなく、おそらく上記のすべてを無視するべきです。これらのアイディアを厳密にする、あるいはそれらがすでに直感的に有用ではない場合にそれらを説明するために私が知る唯一の方法は、最初にあなたに大きなO記法か何かを教えることです。 (ただし、将来、大きなOの表記法をよく理解したら、これらのアイデアを再検討する価値があるかもしれません)

8
Hurkyl

「Big O」表記のわかりやすい英語の説明は何ですか?

非常にクイックノート:

「Big O」のOは「Order」(または正確に「order of」)と呼びます。
だから、それらを比較するために何かを注文するのに使われるという文字通りのアイデアを得ることができます。 

  • "Big O"は2つのことをします:

    1. タスクを達成するためにコンピューターが適用する方法のステップ数を見積もります。
    2. それが良いかどうかを判断するために他の人と比較するためのプロセスを促進しますか?
    3. "Big O 'は標準化されたNotationsで上記2つを達成します。
  • 最もよく使われる表記法が7つあります

    1. O(1)は、あなたのコンピュータが1ステップでうまくいったことを意味します。
    2. O(logN)は、あなたのコンピューターがlogNステップでタスクを完了したことを意味します。
    3. O(N)、Nのステップでタスクを終了する、その公正、注文番号3
    4. O(NlogN)、O(NlogN)ステップでタスクを終了する、それは良くない、注文番号4
    5. O(N ^ 2)、N^2ステップでタスクを完了させる
    6. O(2 ^ N)、2^Nステップで仕事をやり遂げる
    7. O(N!)、N!ステップでタスクを完了させる

enter image description here

O(N^2)という表記があるとします。このメソッドがタスクを達成するためにN * Nのステップを踏むことが明らかであるだけでなく、その順位からO(NlogN)のように良くないこともわかります。

わかりやすくするために、行末の順序に注意してください。すべての可能性を考慮すると、7つ以上の表記があります。

CSでは、タスクを実行するための一連のステップをアルゴリズムと呼びます。
用語では、Big O表記はアルゴリズムのパフォーマンスまたは複雑さを表すために使用されます。

さらに、Big Oは最悪の場合を設定するか、または上限ステップを測定します。
あなたはBig-Ω(Big-Omega)をベストケースとして参照することができます。

Big-Ω(ビッグオメガ)表記(記事)|カーンアカデミー

  • まとめ
    "Big O"はアルゴリズムの性能を説明し評価します。

    あるいは正式に言うと、「Big O」はアルゴリズムを分類し、比較プロセスを標準化します。 

7
JawSaw

それを見るための最も簡単な方法(平易な英語)

入力パラメータの数がアルゴリズムの実行時間にどのように影響するかを調べています。アプリケーションの実行時間が入力パラメータの数に比例する場合、それはnのBig Oにあると言われます。 

上記の記述は良いスタートですが、完全には正しくありません。

より正確な説明(数学的)

と思います

n =入力パラメータ数

T(n)=アルゴリズムの実行時間をnの関数として表す実際の関数

c =定数

f(n)=アルゴリズムの実行時間をnの関数として表す近似関数

その場合、Big Oに関する限り、次の条件が成り立つ限り、近似f(n)は十分に良いと見なされます。

lim     T(n) ≤ c×f(n)
n→∞

Nが無限大に近づくと、nのTは、cのn倍のfに等しいか、それ以下になります。

大きなO記法ではこれは次のように書かれる。

T(n)∈O(n)

これは、nのTがnの大きなOの中にあると解釈されます。

英語に戻る

上の数学的定義に基づいて、あなたのアルゴリズムがnのBig Oであると言うなら、それはそれがn(入力パラメータの数) またはより速い の関数であることを意味します。あなたのアルゴリズムがnのBig Oであれば、それは自動的にnのBig Oの二乗です。 

Nの大きいOは私のアルゴリズムが少なくともこれと同じくらい速く走ることを意味します。あなたはあなたのアルゴリズムのBig O記法を見てそれが遅いと言うことはできません。あなたはその速さを言うことができるだけです。 

UC BerkleyのBig Oに関するビデオチュートリアルは this outにあります。それは実際には単純な概念です。あなたがそれを説明している教授シューチャック(別名神レベルの先生)を聞くならば、あなたは言う「あなたはそれがすべてだ!」と言うでしょう。 

6
developer747

これは非常に単純化された説明ですが、私はそれが最も重要な詳細をカバーすることを願っています。

問題を扱うあなたのアルゴリズムがいくつかの「要因」に依存するとしましょう、例えばそれをNとXにしましょう。

NとXに依存して、あなたのアルゴリズムはいくつかの操作を必要とするでしょう、例えば、最悪の場合それは3(N^2) + log(X)操作です。

Big-Oは定数係数(別名3)をあまり気にしないので、アルゴリズムのBig-OはO(N^2 + log(X))です。それは基本的に「最悪の場合にあなたのアルゴリズムが必要とする演算量はこれに比例する」と言い換えます。

4
nkt

定義: - Big O表記は、データ入力が増加した場合にアルゴリズムのパフォーマンスがどのように実行されるかを示す表記です。 

我々がアルゴリズムについて話すとき、アルゴリズムの入力、出力そして処理の3つの重要な柱があります。 Big Oはシンボリック表記で、データ入力がどの程度の割合で増加した場合、パフォーマンスはアルゴリズム処理によって異なります。

Big O表記法 を詳細に説明したこのYouTubeビデオをコード例でご覧になることをお勧めします。

Algorithm basic pillars

したがって、たとえば、アルゴリズムが5レコードを取り、同じ処理に必要な時間が27秒であるとします。レコードを10に増やすと、アルゴリズムは105秒かかります。

簡単に言うと、所要時間はレコード数の2乗です。これを O(n ^ 2) で表すことができます。この記号表現はBig O表記と呼ばれます。

ここで、単位は入力内の何でもかまいません。バイト、レコードのビット数、パフォーマンスは秒、分、日などの単位で測定できます。だからそれは正確な単位ではなくむしろ関係です。

Big O symbols

例えば、コレクションを取り、最初のレコードを処理する以下の関数 "Function1"を見てください。この機能では、1000、10000、または100000レコードを入力しても、パフォーマンスは同じになります。それで O(1) で表すことができます。

void Function1(List<string> data)
{
string str = data[0];
}

今度は以下の関数 "Function2()"を見てください。この場合、処理時間はレコード数とともに増加します。このアルゴリズムの性能を O(n) を使って表すことができます。

void Function2(List<string> data)
        {
            foreach(string str in data)
            {
                if (str == "shiv")
                {
                    return;
                }
            }
        }

私達があらゆるアルゴリズムのためのBig Oの表記法を見るとき私達は性能の3つの部門にそれらを分類できる: -

  1. ログと定数のカテゴリ: - どの開発者でもこのカテゴリのアルゴリズムのパフォーマンスを見たいと思うでしょう。
  2. 線形: - 開発者は、最後のオプションまたは唯一のオプションが残るまで、このカテゴリのアルゴリズムを見たくありません。
  3. 指数関数: - これが私たちがアルゴリズムを見たくないところであり、手直しが必要です。

そのため、Big O記法を見て、アルゴリズムの良いゾーンと悪いゾーンを分類します。

Bog O classification

サンプルコード付きのBig Oについて説明したこの10分間のビデオを見ることをお勧めします。

https://www.youtube.com/watch?v=k6kxtzICG_g

4

これを6歳の子供に説明したいのであれば、例えばf(x) = xとf(x) = x ^ 2という関数を書き始めます。どの関数がページ上部の上位関数になるかを示す子です。それでは描画を進めていき、x ^ 2が勝つことを確かめましょう。 「誰が勝つか」は実際にはxが無限大になる傾向があるときより速く成長する関数です。したがって、「関数xがx ^ 2のBig Oにある」とは、xが無限大になる傾向があるときにxがx ^ 2よりも遅くなることを意味します。 xが0になるときにも同じことができます。xについてこれら2つの関数を0から1まで描くと、xは上限関数になるので、 "function x ^ 2はxのBig Oになります。 0歳まで。子供が年をとるにつれて、私は本当にBig Oは速くはないが与えられた関数と同じように成長する関数になることができると付け加えます。さらに定数は破棄されます。つまり2xはxのBig Oにあります。

3
user3745123

序文

algorithm:問題を解決するための手順/公式


どのようにアルゴリズムを分析し、どのようにしてアルゴリズムを互いに比較できますか?

例: あなたと友人は0からNまでの数字を合計する関数を作るように頼まれます。あなたはf(x)を考え出し、あなたの友人はg(x)を考えます。どちらの関数も同じ結果になりますが、アルゴリズムは異なります。アルゴリズムの効率を客観的に比較するために、Big-O表記を使用します。

Big-O記法:は、 入力が任意に大きくなるにつれて、入力に対してランタイムがどれだけ速くなるのかを説明します

3の主な問題点:

  1. 比較 どのくらい速くランタイムが成長するNOT正確なランタイムを比較する (ハードウェアに依存する)
  2. 実行時間の増加のみに関係します。入力(n)と比較します。
  3. n が任意に大きくなるにつれて、nが大きくなるにつれて最も速く成長する項に注目してください(無限大と考えてください)。AKA 漸近解析

スペースの複雑さ:時間の複雑さの他に、スペースの複雑さ(アルゴリズムが使用するメモリー/スペースの量)にも注意します。操作の時間を確認する代わりに、メモリの割り当てサイズを確認します。

3
Ryan Efendy

特に数学にあまり興味がない人のために、私は大きなO記法について本当に素晴らしい説明を見つけました。

https://rob-bell.net/2009/06/a-beginners-guide-to-big-o-notation/ /

Big O記法は、計算機科学において、アルゴリズムの性能または複雑さを記述するために使用されます。 Big Oはワーストケースのシナリオを具体的に説明しており、アルゴリズムによって必要な実行時間または使用されているスペース(メモリやディスク上など)を説明するために使用できます。 。

Programming Pearlsや他のComputer Science の本を読んでいて、数学に根拠のない人は、O(N log N)などの章に到達したときに壁にたどり着くでしょう。 クレイジーな構文この記事が、Big OとLogarithmsの基本についての理解を深めるのに役立つことを願っています。

プログラマーが最初で数学者が2番目(またはおそらく3番目または 4番目)として、Big Oを完全に理解するための最善の方法は、コード内にいくつかの例を作成することです。それで、以下は可能なところでの説明と例と共に成長のいくつかの一般的な順序です。

O(1)

O(1)は、入力データセットのサイズに関係なく、常に同じ時間(またはスペース)に実行されるアルゴリズムを表します。

bool IsFirstElementNull(IList<string> elements) {
    return elements[0] == null; } O(N)

O(N)

O(N)は、その性能が線形的に、そして入力データセットのサイズに正比例して増大するアルゴリズムを記述する。以下の例も、Big Oが最悪の場合のパフォーマンスシナリオをどのように優先するかを示しています。 forループの反復中に一致する文字列が見つかると、関数は早く戻りますが、Big O表記は常にアルゴリズムがを実行する上限を想定します。最大反復回数。

bool ContainsValue(IList<string> elements, string value) {
    foreach (var element in elements)
    {
        if (element == value) return true;
    }

    return false;
} 

2

2)は、その性能が入力データセットのサイズの2乗に正比例するアルゴリズムを表します。これは、データセットに対して入れ子になった反復を含むアルゴリズムと共通です。より深い入れ子反復はO(N)になります3)、O(N)4)など.

bool ContainsDuplicates(IList<string> elements) {
    for (var outer = 0; outer < elements.Count; outer++)
    {
        for (var inner = 0; inner < elements.Count; inner++)
        {
            // Don't compare with self
            if (outer == inner) continue;

            if (elements[outer] == elements[inner]) return true;
        }
    }

    return false;
}

O(2N

O(2N)は、その成長が入力データセットへのの追加ごとに2倍になるアルゴリズムを示します。 O(2の成長曲線N)関数は指数関数です - 非常に浅いところから始まり、その後は気象的に上昇します。 O(2)のの例N)関数はフィボナッチ数の再帰計算です。

int Fibonacci(int number) {
    if (number <= 1) return number;

    return Fibonacci(number - 2) + Fibonacci(number - 1);
}

対数

対数は説明が少し難しいので、一般的なの例を使用します。

バイナリ検索は、ソートされたデータセットを検索するために使用される手法です。それは、データセットの中央の要素、本質的には中央値の中央値を選択することによって機能し、それを目標値と比較する。値が一致すればは成功を返します。目標値がプローブ要素の値よりも高い場合は、データセットの上半分を使用し、それに対して同じ操作を実行します。同様に、目標値がプローブエレメントの値より低い場合、下半分に対して操作を実行します。値が見つかるまで、またはデータセットを分割できなくなるまで、反復ごとにデータセットを半分にし続けます。

この種のアルゴリズムはO(log N)と表記されます。二分探索の例に記載されているデータセットの反復二分の一[....]は、始めにピークに達し、データセットのサイズ[... 10個の項目を含む入力データセットが完了するまで1秒かかり、100個の項目を含むデータセットは[2秒]かかり、1000個の項目を含むデータセットは3秒かかります。入力データセットのサイズを2倍にしても、アルゴリズムの1回の反復後にデータセットが半分になり、したがって入力データセットの半分に相当する場合には、の増加にはほとんど影響しません。 サイズこれにより、大きなデータセットを扱うときに、バイナリサーチのようなアルゴリズムが非常に効率的になります。

3
SIW

Big Oは関数のクラスを説明しています。

大きな入力値に対して関数がどれだけ速く成長するかを説明します。

与えられた関数fに対して、O(f)はn0と定数cを見つけることができるすべての関数g(n)を記述し、g(n)はc * f(n)以下である

より数学的でない言葉では、O(f)は関数の集合です。つまり、ある値n0以降のすべての関数は、fより遅くなったり、fと同じくらい速くなっています。

f(n) = nの場合 

g(n)= 3nはO(f)の中にあります。定数の要素は関係ないからです。 h(n)= n + 1000はO(f)の中にあるので大きくなります。すべての値は1000より小さいですが、大きいOの場合は巨大な入力のみが重要です。

ただし、2次関数は線形関数よりも速く成長するため、i(n) = n ^ 2はO(f)には含まれません。

2
xuma202

Big Oは、関数の上限を表すための手段です。アルゴリズムの実行時間を指示する関数の上限を表現するために一般的にそれを使用します。

Ex:f(n) = 2(n ^ 2)+ 3nは仮想アルゴリズムの実行時間を表す関数であり、Big-O表記は本質的にこの関数の上限をOとする(n ^ 2)

この記法は基本的に、どの入力 'n'に対しても、実行時間はBig-O記法で表される値よりも長くならないことを示しています。

また、上記のすべての詳細な回答に同意してください。お役に立てれば !!

2
user3170122

これは、ロングランのアルゴリズムの速度を表します。

文字通りの類推をするために、ランナーが100mのダッシュ、または5kのランをどれだけ速く走れるかは気にしません。マラソン選手、そしてできればウルトラマラソン選手をもっと気にかけます(それを超えると、ランニングとの類似性が崩れ、「長期」の比phor的な意味に戻らなければなりません)。

ここで読むのを安全に停止できます。

私はこの答えを追加しています。なぜなら、残りの答えが数学的にも技術的にも驚いているからです。最初の文の「長期」の概念は、任意の時間を消費する計算タスクに関連しています。人間の能力によって制限される実行とは異なり、計算タスクは特定のアルゴリズムが完了するまでに数百万年以上かかる場合があります。

それらのすべての数学的な対数多項式はどうですか?アルゴリズムは、これらの数学用語に本質的に関連することがわかります。ブロック上のすべての子供の身長を測定している場合、子供がいるのと同じくらい時間がかかります。これは本質的にn ^ 1または単にnの概念に関連していますここで、nはブロック上の子供の数にすぎません。ウルトラマラソンの場合、あなたはあなたの街のすべての子供の身長を測定していますが、旅行時間を無視し、すべての子供が列に並んでいると仮定する必要があります(そうでなければ、現在の説明より先にジャンプします)。

次に、作成した子供の身長のリストを、最短身長から最長身長の順に並べようとしているとします。それがあなたの近所の子供たちだけであるなら、あなたはそれをただ目で見て、順序付けられたリストを思いつくかもしれません。これは「スプリント」の類推であり、コンピューターサイエンスのスプリントについては本当に気にしません。なぜなら、何かを目で見られるときにコンピューターを使用するのはなぜですか

しかし、あなたの街のすべての子供たちの身長のリストを整理している場合、またはより良いことにあなたの国の場合、それを行う方法は本質的に数学的なlogおよび- n ^ 2。リストを調べて最短の子供を見つけ、彼の名前を別のノートブックに書き、元のノートブックから消すことは、本質的に数学と結びついていますn ^ 2。ノートブックの半分を配置し、次に他の半分を配置し、結果を結合することを考えると、本質的にに結び付けられたメソッドに到達します対数

最後に、最初に店に行って測定テープを購入しなければならなかったと仮定します。これは、ブロック上の子供を測定するなど、短いスプリントで重要な努力の例ですが、市内のすべての子供を測定する場合は、このコストを安全に無視できます。これは、たとえば低次の多項式項の数学的削除への本質的な関係です。

Big-O表記は単に長い目で見たものであり、数学は本質的に計算の方法に関係していること、数学用語や他の単純化の削除はかなり一般的な意味で長い目で見られることを説明したことを願っています方法。

これに気付くと、高校生の数学はすべて簡単に抜け落ちてしまうので、big-Oは本当に超簡単だとわかります。唯一の難しい部分は、アルゴリズムを分析して数学用語を特定することですが、一部の練習では、分析自体の間に用語のドロップを開始し、アルゴリズムのチャンクを安全に無視して、big-Oに関連する部分のみに焦点を当てることができます。 I. e。ほとんどの状況を目で確認できるはずです。

幸運なことに、それはコンピューターサイエンスに関する私のお気に入りでした-何かが思っていたよりもずっと簡単であることに気付き、それからGoogleのインタビューで未経験者が威圧されると誇示できるようになりました(笑)。

2
user2297550

平易な英語でのBig Oは<=(より小さいか等しい)のようなものです。 2つの関数fとgについて言うと、f = O(g)はf <= gを意味します。 

ただし、これはn f(n) <= g(n)を意味するわけではありません。実際には、 fは成長の観点からg以下であるということです cが定数 の場合、 点の後 f(n) <= c * g(n)になります。そして 点の後 はすべてのn> = n0よりも大きいことを意味します。ここで、n0 は別の定数です .

2
A. Mashreghi

「Big O」表記のわかりやすい英語の説明は何ですか?

アルゴリズムの入力サイズが 大きすぎる 式を記述する一部の部分(すなわち定数、係数、項)になるとき、“ Big O”表記の動機は1つのことであることを強調したいと思います。アルゴリズムの尺度は それほど重要ではない 私たちが 無視する になります。その一部を無視した後も存続する方程式の一部は、アルゴリズムの“ Big O”表記法と呼ばれます。 

そのため、入力サイズがそれほど大きくない場合、“ Big O”表記(上限)の考え方は重要ではありません。 


Lesは、次のアルゴリズムの性能を定量化したいと言っています

int sumArray (int[] nums){
    int sum=0;   // taking initialization and assignments n=1
    for(int i=0;nums.length;i++){
        sum += nums[i]; // taking initialization and assignments n=1
    }
    return sum;
}

上記のアルゴリズムで、T(n)を次のように見つけたとしましょう(時間の複雑さ)。 

T(n) = 2*n + 2

その「Big O」表記を見つけるには、非常に大きな入力サイズを考慮する必要があります。

n= 1,000,000   -> T(1,000,000) = 2,000,002
n=1,000,000,000  -> T(1,000,000,000) = 2,000,000,002
n=10,000,000,000  -> T(10,000,000,000) = 20,000,000,002

他の関数についても同様の入力をしましょうF(n) = n

n= 1,000,000   -> F(1,000,000) = 1,000,000 
n=1,000,000,000  -> F(1,000,000,000) = 1,000,000,000
n=10,000,000,000  -> F(10,000,000,000) = 10,000,000,000

あなたが入力サイズとして得ることができるように見ることができる 大きすぎるT(n)F(n)にほぼ等しいか近づくので、定数2と係数2はあまりにも重要ではなくなりました 

O(T(n)) = F(n)
O(T(n)) = n

T(n)の大きいOはnであり、その表記はO(T(n)) = nであり、nが得るようにT(n)の上限である 大きすぎる 。同じ手順が他のアルゴリズムにも適用されます。

TLDR:Big Oは、アルゴリズムの性能を数学的に説明しています。 

より遅いアルゴリズムは、その深さに応じて、nのx乗またはxの倍数で実行される傾向がありますが、バイナリ検索のような高速のアルゴリズムはO(log n)で実行され、データセットが大きくなるにつれて高速で実行されます。 Big Oは、nを使って他の用語で説明することも、nを使用しないことで説明することもできます(例:O(1))。

Big Oを計算することができますアルゴリズムの最も複雑な行を見てください。

小規模またはソートされていないデータセットでは、バイナリ検索のようなn log n複雑さのアルゴリズムは、バイナリ検索に対するバイナリ検索の単純な実行例では遅くなる可能性があるため、驚くことがあります。

https://codepen.io/serdarsenay/pen/XELWqN?editors=1011 (下記のアルゴリズム)

function lineerSearch() {
  init();
  var t = timer('lineerSearch benchmark');
  var input = this.event.target.value;
  for(var i = 0;i<unsortedhaystack.length - 1;i++) {
    if (unsortedhaystack[i] === input) {
      document.getElementById('result').innerHTML = 'result is... "' + unsortedhaystack[i] + '", on index: ' + i + ' of the unsorted array. Found' + ' within ' + i + ' iterations';
      console.log(document.getElementById('result').innerHTML);
      t.stop(); 
      return unsortedhaystack[i]; 
    }
  }
}

function binarySearch () {
  init();
  sortHaystack();
  var t = timer('binarySearch benchmark');
  var firstIndex = 0;
  var lastIndex = haystack.length-1;
  var input = this.event.target.value;

  //currently point in the half of the array
  var currentIndex = (haystack.length-1)/2 | 0;
  var iterations = 0;

  while (firstIndex <= lastIndex) {
    currentIndex = (firstIndex + lastIndex)/2 | 0;
    iterations++;
    if (haystack[currentIndex]  < input) {
      firstIndex = currentIndex + 1;
      //console.log(currentIndex + " added, fI:"+firstIndex+", lI: "+lastIndex);
    } else if (haystack[currentIndex] > input) {
      lastIndex = currentIndex - 1;
      //console.log(currentIndex + " substracted, fI:"+firstIndex+", lI: "+lastIndex);
    } else {
      document.getElementById('result').innerHTML = 'result is... "' + haystack[currentIndex] + '", on index: ' + currentIndex + ' of the sorted array. Found' + ' within ' + iterations + ' iterations';
      console.log(document.getElementById('result').innerHTML);
      t.stop(); 
      return true;
    }
  }
}
0
serdarsenay

大きなO - 経済の見方。  

この概念を説明するための私のお気に入りの英単語は 価格 /あなたはそれがより大きくなるにつれてあなたがタスクに支払う。 

あなたが最初に支払うであろう固定費の代わりに経常費用と考えてください。固定費は全体像では無視できるほどになります。これは、費用が増加して合計されるためです。我々は、彼らがどのくらい速く成長するか、そして我々が設定に与える原材料に関してどれほど早くそれらが合算するかを測定したい - 問題の大きさ。 

ただし、初期設定コストが高く、少量の製品しか生産しない場合は、これらの初期コストを検討する必要があります。これらは定数とも呼ばれます。

これらの定数は長期的には問題にならないので、この言語を使用すると、どのようなインフラストラクチャで実行しているのかを超えたタスクについて議論できます。だから、工場はどこにでもでき、労働者はだれでもかまいません - それはすべて肉汁です。しかし、工場の規模と労働者の数は、あなたのインプットとアウトプットが成長するにつれて、長期的には変化する可能性があるものです。 

したがって、これは 全体像の近似値 に何かを実行するために費やす必要がある金額になります。ここで、 time space は経済的な量であるため(つまり制限されているため)、両方ともこの言語を使用して表すことができます。 

テクニカルノート:時間の複雑さの例 - O(n)は、問題のサイズが 'n'の場合、少なくともすべてを確認する必要があることを意味します。 O(log n)は、通常、問題のサイズを半分にして、タスクが完了するまでチェックして繰り返すことを意味します。 O(n ^ 2)は物事のペアを見る必要があることを意味します(n人のパーティーでの握手のように)。 

0
snagpaul