これは技術的には「Hello World」のO(1)アルゴリズムですか?


117

これは「Hello、World!」のO(1)アルゴリズムとして分類されますか???

public class Hello1
{
   public static void Main()
   {
      DateTime TwentyYearsLater = new DateTime(2035,01,01);
      while ( DateTime.Now < TwentyYearsLater )
      { 
          System.Console.WriteLine("It's still not time to print the hello ...");
      }
      System.Console.WriteLine("Hello, World!");
   }
}

私は使用することを考えています

DateTime TwentyYearsLater = new DateTime(2035,01,01);
while ( DateTime.Now < TwentyYearsLater )
{ 
   // ... 
}

誰かが特定の複雑さのアルゴリズムを要求するたびに冗談として入れられるビジーループとしてのコードのスニペット。これは正しいでしょうか?


15
これはO(N)複雑ではありませんO(1)
Fabjan

19
@SubparWebDevいいえ、プログラムを開始してから指定した日付までの正確な時間差がわかっていても、ループを何回繰り返すかわかりません。それはどのくらいの速などその上で実行されている他に何それが実行しているコンピュータ、どのようにCPUのスケジュールタスクに依存します
Servy

131
@Fabjan Nアルゴリズムが依存しているわけではないので、実際にO(N)アルゴリズムであるとは言えません。
サービー

29
技術的には入力Nがないため、意味がありません。ただしDateTime.Now、これが結果に依然依存するような入力を検討することもできます。の現実的な値を想定できる場合DateTime.Nowは、はい、プログラムは一定回数ループします。
突く

43
問題ステートメントは、Nが何であるかを定義する必要があります。
Yacoub Massad

回答:


406

このコンテキストでのBig O表記は、関数の入力のサイズと、その入力の結果を計算するために実行する必要がある操作の数との関係を表すために使用されています。

操作には、出力を関連付けることができる入力がないため、Big O表記の使用は無意味です。操作にかかる時間は、操作の入力とは無関係です(...なし)。入力と実行された操作の数の間に関係がないため、Big Oを使用して、存在しない関係を記述することはできません


6
どうO(max(1, 2035 - yearTheProgramIsStarted))ですか?
Bergi

19
@Bergi [実際にはありません((stackoverflow.com/questions/34048740/…))。ジョブを実行した時間のみに基づいてループの反復回数を単に説明することはできません。そしてもちろん、それをユーザーがシステムクロックをいつでも好きなときに変更できるという事実と組み合わせることができます。さらに、いくつかの要素に正確に関連付けることができる整形式の入力がまだありません。出力を生成するために必要な操作。いや、出力自体も一貫していません。
15

23
システムの状態(クロックを含む)はプログラムの入力の一部であると主張することができます。その意味では、明示的ではありませんが、日付を入力パラメーターとして使用できます。しかし、それは奇妙です。
Connor Clark

9
より明確にするために、「暗黙の」入力は2035年1月1日と今日の間のデルタです。
Connor Clark

6
@Hotenただし、システム時間は固定値ではありません。この関数は、開始時間のa を入力として受け入れるだけではありませんDateTime。先に述べたように、システムクロックは時間とともに変化する可能性があります。また、説明しているquazi入力を固定出力に直接マッピングすることはできません。所定の開始時間に対して実行される既知の数の操作はありません。また、常に有意な値を得る2つのプログラムについてもDateTime.Now、時間の変化に応じて2つを関連付けることはできません。時間変わりません
サービー

88

Big-O表記は、おおよそ「作業量Nに対する演算を与えられた場合、Nに比例して計算時間はどれくらいかかりますか?」を意味します。たとえば、サイズNの配列のソートには、N ^ 2、Nlog(N)などを使用できます。

これには、作用する入力データの量はありません。そうではありませんO(anything)

さらに悪いことに これは厳密にはアルゴリズムではありません。アルゴリズムは、数学関数の値を計算する方法です。数学関数は、1つの入力から出力へのマッピングです。これは入力を取らず、何も返さないので、数学的な意味では関数ではありません。ウィキペディアから:

アルゴリズムは、限られた量の空間と時間内で、関数を計算するための明確に定義された形式言語で表現できる効果的な方法です。命令は、初期状態と初期入力(おそらく空)から始まり、実行時に明確に定義された連続した状態の有限数を介して進み、最終的に「出力」を生成し、最終的な終了状態で終了する計算を記述します。

これは、技術的には制御システムです。ウィキペディアから;

制御システムは、他のデバイスまたはシステムの動作を管理、コマンド、指示、または規制するデバイスまたはデバイスのセットです。

数学関数とアルゴリズムの違い、およびコンソール出力、グラフィックスの表示、ロボットの制御などの副作用を行うコンピューターのより強力な機能について、より詳細な答えを求めている人は、このペーパーを読んでください。強い教会チューリング仮説

概要

位置計算を入力への入力(有理数または有限文字列)から出力へのクローズドボックス変換として計算する古典的なビュー。コンピューティングのインタラクティブなビューによれば、計算は、入力から出力への関数ベースの変換ではなく、進行中のインタラクティブなプロセスです。具体的には、外界との通信は、計算の前後ではなく、計算中に行われます。このアプローチは、計算とは何か、それがどのようにモデル化されるかについての理解を根本的に変えます。

新しいパラダイムとしての相互作用の受け入れは、チューリングマシン(TM)がすべての計算をキャプチャーするという広く信じられている強い教会チューリング論文(SCT)によって妨げられているため、TMよりも表現力のある計算モデルは不可能です。このホワイトペーパーでは、SCTが元のChurch-Turing論文(CTT)を、チューリングが意図していない方法で再解釈することを示します。オリジナルと同等であると一般的に想定されているのは神話です。SCTに対する幅広い信念の歴史的な理由を特定して分析します。それが偽であることを受け入れることによってのみ、相互作用を計算の代替パラダイムとして採用し始めることができます


シーケンスである必要はありません。これは単なるデータ入力であり、ランダウ記法はそのデータのいくつかのメトリック(通常はサイズに関連するもの)に関連して実行時間を表します。
Bergi、2015

@Bergi-ええ、あなたの要点を見てください!実際には、概算を行うだけですが、そうです。実行する作業量と、そこに到達するまでのステップ数を測定できれば、big-oはこれら2つの測定値の関係を反映しています。クローザー?
Steve Cooper、

@kapep-voidメソッドであるため、純粋な関数ではありませんが、コンソール出力を数えると、ランダムです。{"Hello、World!"、 "まだhelloを印刷する時間ではありません... \ nHello、World!"、 "まだhelloを印刷する時間ではありません...まだ印刷する時間ではありませんこんにちは... \ nHello、World! "、...}
Steve Cooper

1
stdoutへの出力は出力ではありませんか?
rpax

4
@rpax数学的にではなく、違います。関数は、入力から出力への不変の変換です。たとえば、 'square'は、3を入力すると常に9を返す関数です。c#メソッドは、同じパラメーターを使用した呼び出しが常に同じ戻り値を返す場合の数学関数にすぎません。それ以外の場合-コンソールへの書き込み、グラフィックスの表示、メモリの割り当てなどの副作用がある場合-これらは数学関数ではありません。(私の答えへのリンクを追加します。それは耐え難いほど詳細に記載されています:))
Steve Cooper

41

いいえ、コードの時間の複雑さはO(2^|<DeltaTime>|)

現在時刻の適切なコーディングについて。
まず、私の英語をお詫び申し上げます。

CSでのBig Oとは

Big O表記は、プログラムの入力とその実行時間を結び付けるために使用されません
Big O表記は、厳密さを残して、2つの量の漸近比を表す方法です。

アルゴリズム分析の場合、これらの2つの量は入力ではなく(最初に「メジャー」関数が必要)、実行時間ではありません。
それらは、問題1のインスタンスのコーディングの長さと、対象のメトリックです。

一般的に使用される指標は

  1. 特定の計算モデルでアルゴリズムを完了するために必要なステップ数。
  2. そのような概念が存在する場合、計算モデルが必要とするスペース。

最初のポイントが遷移2関数の適用回数、つまり「ステップ」に変換され、2番目のポイントが少なくとも1回書き込まれたさまざまなテープセルの数に変換されるように、モデルとして暗黙的にTMが想定さます。

多くの場合、元のエンコーディングの代わりに多項式関連のエンコーディングを使用できると暗黙のうちに想定されていますか。たとえば、配列を最初から最後まで検索する関数は、そのO(n)ような配列のインスタンスのコーディングの長さがn*b+(n-1)ここbで、は各要素のシンボルの(定数)数です。これは、bが計算モデルの定数と見なされるため、上の式とn漸近的に同じだからです。

これはまた、トライアルディビジョンのようなアルゴリズムが、本質的には類似のアルゴリズムであるにもかかわらず、指数アルゴリズムであることを説明していfor(i=2; i<=sqr(N); i++)ます3

参照してくださいこれを

これはまた、大きなO表記は、問題を説明するために必要な数のパラメーターを使用する可能性があることを意味します。一部のアルゴリズムではkパラメーターを持つことは珍しくありません。

したがって、これ「入力」または「入力がない」ということではありません。

今の研究事例

Big O表記は、アルゴリズムに疑問を投げかけるものではなく、単に何をしているのかを知っていると仮定しているだけです。それは本質的にあらゆる場所に適用可能なツールであり、故意にトリッキーな(あなたのような)アルゴリズムにも適用できます。

問題を解決するために、現在の日付と将来の日付を使用したので、それらはどういうわけか問題の一部であるに違いありません。簡単に言うと、それらは問題のインスタンスの一部です。

具体的には、インスタンスは次のとおりです。

<DeltaTime>

ここで、<>手段とは、任意の非病理的な選択のコーディングを意味します。

非常に重要な説明については、以下を参照してください。

したがって、O(2^|<DeltaTime>|)現在の時間の値に依存する多数の反復を実行するため、大きなOの複雑度の時間はちょうどになります。漸近表記は定数を削除するため便利です(たとえば、の使用O(10^|<DeltaTime>|*any_time_unit)は無意味です)ので、他の数値定数を置く意味はありません。

トリッキーな部分はどこですか

上記の重要な仮定の1つを作成しました。計算モデルは5時間を意味し、時間によって私は(実際の?)物理時間を意味します。標準的な計算モデルにはそのような概念はありません。TMは時間を知りません。これが私たちの現実が機能する方法であるため、時間とステップ数を関連付けます4

モデルでは時間は計算の一部ですが、Mainは純粋ではないが概念は同じであると言うことで、機能的な人々の用語を使用できます。

これを理解するには、フレームワークが物理的な時間の2倍、5倍、10倍速い偽の時間を使用することを妨げるものがないことに注意する必要があります。このようにして、コードは「時間」の「半分」、「1/5」、「1/10」で実行されます。

このリフレクションは、のエンコーディングを選択するために重要です<DeltaTime>。これは、本質的に<(CurrentTime、TimeInFuture)>を書くための凝縮された方法です。事前には時間が存在しないため、CurrentTimeのコーディングは、Now(または他の任意の選択)を前日のようにコーディングして、昨日としてコーディングすることができます。これにより、コーディングの長さが増加するという仮定が破られます。、物理的な時間として進む(そしてDeltaTimeの1つが減少する)

何か有用なことをするために、計算モデルで時間を適切にモデル化する必要があります。

私たちができる唯一の安全な選択は、物理的な時間ステップが進むにつれて、長さが増すタイムスタンプをエンコードすることです(ただし、単項を使用しません)。これは私たちが必要とする唯一の真の時間特性であり、エンコーディングがキャッチする必要のある特性です。アルゴリズムに時間の複雑さが与えられる可能性があるのは、このタイプのエンコーディングでのみですか?

あなたの混乱は、もしあれば、ワードという事実から生じた時間の句で「そのある何時間複雑?」と 'どのくらいの時間がかかりますか?」非常に異なることを意味します

悲しいことに同じ用語を使用していますが、「ステップの複雑さ」を頭の中で試してみて、もう一度質問してください。答えが本当に^ _ ^であることを理解するのに役立つと思います


1これはまた、各インスタンスの長さが異なるが任意ではないため、漸近的なアプローチの必要性を説明します。
2ここで正しい英語の用語を使用しているといいのですが。
3また、これがlog(log(n))数学で用語を見つけることが多い理由でもあります。
4間違いなく、ステップは、有限の時間間隔を占有する必要がありますが、ヌルでも接続でもありません。
5これは、その中の物理的な時間の知識としての計算モード、つまり、それをその用語で表現できることを意味します。アナロジーは、ジェネリックが.NETフレームワークでどのように機能するかです。


3
「だからあなたのビッグOの実行時間はちょうどです」..あなたが「ビッグOの複雑さ」を意味していたと確信していますか?また、「deltaTime」を「n」権限と呼ぶこともできます。つまり、フィボナッチアルゴリズムの複雑さのようなO(2 ^ N)を言います。どうして「2 ^」に来たのですか?
ロス、

@ロス、要点をありがとう。私は2進数を扱う習慣が2つ付いてきました。ポイントは、ステップが数の表現の長さと線形であることです。実際のベースはそれほど重要ではなく、特定のエンコーディングに基づいて異なります。それは擬似線形
Yuni Mj

申し訳ありませんが、複雑さをどのように結論付けたのか、回答を詳しく説明してもらえますO(2^n)か?初心者にはわかりません。
Arturo TorresSánchez15年

2
@YuniMjあなたの推論は技術的に間違っているわけではありませんが、ではなくサイズを測定するように主張することで、混乱がさらに増すだけだと思います。たとえば、ただし、その理由付けには、最適な並べ替えアルゴリズムには$ O(n \ cdot log n)$の時間の複雑さはありません。どうして?ソートできる識別可能なオブジェクトは有限であるか、その場合は常にバケットソートを使用して$ O(n)$でソートできます。または、オブジェクトサイズが無制限である場合、単一の比較では一定の時間がなくなるため、$ O(n \ cdot log n)$は保持されません...DeltaTime
fgp

1
FWIW O(2 ^ N)= O(10 ^ N)!stackoverflow.com/questions/19081673/...
ネイサンFD

29

ここにはたくさんの素晴らしい答えがありますが、それらすべてを少し言い換えてみましょう。

関数を説明するためにBig-O表記が存在します。アルゴリズムの分析に適用する場合、関数の観点からこのアルゴリズムのいくつかの特性を最初に定義する必要があります。一般的な選択は、入力サイズの関数としてステップ数を考慮することです。他の回答で述べたように、明確に定義された「入力」がないため、あなたのケースでそのような関数を思い付くのは奇妙に見えます。ただし、まだそれを試すことができます。

  • アルゴリズムは、任意のサイズの任意の入力を受け取り、それを無視し、一定の時間待機して終了する定数関数と見なすことができます。この場合、そのランタイムはf(n)= constであり、O(1)時間アルゴリズムです。これはあなたが聞いて期待していたものですよね?はい、技術的にはO(1)-algorithmです。
  • TwentyYearsLaterは、「入力サイズ」のようなパラメータと見なすことができます。この場合、ランタイムはf(n)=(nx)です。ここで、xは呼び出し時の「現在時刻」です。このように見た場合、これはO(n)時間アルゴリズムです。技術的にO(1)アルゴリズムを他の人に見せようとするときはいつでも、この反論を期待してください。
  • ああ、でも、k =TwentyYearsLaterが入力である場合、そのサイズ nは、実際にはそれを表すために必要なビット数、つまりn = log(k)です。したがって、入力nのサイズとランタイムの間の依存関係は、f(n)= 2 ^ n-xです。アルゴリズムが指数関数的に遅くなったようです!ああ。
  • プログラムへの別の入力は、実際には、ループ内の呼び出しのシーケンスに対してOSによって与えられた応答ストリームですDateTime.Now。このシーケンス全体は、プログラムを実行した瞬間に入力として提供されることを実際に想像できます。ランタイムは、このシーケンスのプロパティ、つまり最初のTwentyYearsLater要素までの長さに依存すると見なすことができます。この場合、ランタイムは再びf(n)= nであり、アルゴリズムはO(n)です。

しかし、繰り返しになりますが、あなたの質問では、ランタイムに興味があるとさえ言っていません。メモリ使用を意味する場合はどうなりますか?状況をどのようにモデル化するかに応じて、アルゴリズムはO(1)-memoryまたはおそらくO(n)-memoryであると言えます(の実装DateTime.Nowで、呼び出しシーケンス全体を追跡する必要がある場合)。

そして、あなたの目標が不合理なものを思いつくことであるなら、あなたはすべてに入って、画面上のピクセル単位のアルゴリズムのコードのサイズが選択されたズームレベルにどのように依存するかに興味があると言いませんか?これはf(zoom)= 1 / zoomのようなもので、アルゴリズムをO(1 / n)ピクセルサイズであると誇らしげに宣言できます。


+1。「OSがDateTime.Now呼び出しのシーケンスに与える回答のストリーム」は、ここでの実際の入力であると思います。しかし、O(n)であるという結論ではなく、O(k)であると思います。最初のTwentyYearsLater要素まで
2015

7
これが今のところ最良の答えです。BigOを意味のあるものにするためには、物理​​的な実装に数学的な意味論/仮定を適用する必要があります(本質的に、「入力」の意味のある定義でプログラムの数学モデルを定義します)。この意味で、「プログラム」の複雑さは適用するセマンティクスに依存します。Nが操作の数に比例する時間差であると仮定すると、それはO(n)です。一定期間の結果として一定数の操作を想定すると、それはO(1)になります。
Ant P

21

私はServyに少し同意しなければなりません。明らかではない場合でも、このプログラムへの入力があり、それはシステムの時間です。これはあなたが意図していなかった専門性かもしれませんが、あなたのTwentyYearsFromNow変数はシステムの時から20年ではありません、2035年1月1日に静的に割り当てられています。

したがって、このコードを取得して、1970年1月1日のシステム時刻を持つマシンで実行した場合、コンピューターの速度に関係なく、完了するまでに65年かかります(クロックに問題がある場合は、多少のばらつきがある可能性があります) )。このコードを取得して、システム時刻が2035年1月2日のマシンで実行すると、ほぼ即座に完了します。

私はあなたの入力を言うでしょうnJanuary 1st, 2035 - DateTime.Now、それ O(n)です。

次に、操作の数の問題もあります。一部の人々は、より高速なコンピュータはより速くループにヒットし、より多くの操作を引き起こすと述べていますが、それは無関係です。big-O表記を使用する場合、プロセッサーの速度や正確な操作数は考慮されません。このアルゴリズムを使用してコンピューターで実行した後、もう一度実行した場合、同じコンピューターで10倍長く実行すると、操作の数は同じ10倍に増えると予想されます。

これについては:

[編集されたコード]のコードスニペットをビジーループとして使用して、誰かが特定の複雑さのアルゴリズムを要求するたびにジョークとして挿入することを考えています。これは正しいでしょうか?

いいえ、そうではありません。他の回答がこれをカバーしているので、私はそれについて述べたかっただけです。一般的に、何年もの実行をBig-O表記に関連付けることはできません。例えば。20年間の執行= O(n ^ 87)などと言うことはできません。あなたが与えたアルゴリズムでもTwentyYearsFromNow、20110、75699436、123456789のいずれかに変更することができ、big-OはO(n)のままです。


7
時間は関数への入力ではなく、メソッドの実行全体を通して観察される、常に変化する状態です。関数の実行中にシステムクロックを変更することもできます。Big Oを意味のあるものにするためには、各入力を1対1で出力値に対応させる必要があります。また、それを計算するために必要ないくつかの演算も必要です。この操作の場合、実行される操作の数も大きく変動することに加えて、同じ入力に対して出力は一貫していません(実際には、大幅に変動します)。
サービー、2015

When working with big-O notation, we don't consider the speed of the processor or the exact number of operations.これは誤った説明です。Big O値を計算しようとする賢明な操作のほとんどは、ハードウェアに基づいて実行される操作の数を変更しませんが、これは変更します。Big Oは、操作の数を入力のサイズに関連付ける方法の1つにすぎません。システムハードウェアに依存しないほとんどの操作。 この場合はそうではありません
サービー

If you took this algorithm and ran it on a computer, and then ran it again but for 10x longer on the same computer, you would expect the number of operations to grow by the same factor of 10x.それもまた虚偽の陳述です。環境は必ずしもループ内の操作の数を直線的に変更するわけではありません。たとえば、さまざまな時点でCPU時間を多かれ少なかれ使用して、このアプリケーションに与えられる時間を常に変化させている他のプログラムがコンピューター上にある可能性があります。
サービー

私はこれで@Servyを使っていますが、少し異なる理由があります。メイン関数はパラメーターをとらず、入力を返しません。お好みでnil => nilの関数です。時間は関係ありませんが、何も返されません。
スティーブクーパー

1
この定義を使用している場合、「数学では、関数は入力のセットと許容される出力のセットとの間の関係であり、各入力は正確に1つの出力に関連付けられているという特性があります。」(ウィキペディア)-コンソール出力を「関数の出力」として数えていますが、これは変化します。高速のコンピューターでは「こんにちは...より頻繁に。
スティーブクーパー

13

Big-O分析は、処理されるデータの量が無制限に増加するため、関連する処理量を扱います。

ここでは、固定サイズの単一のオブジェクトのみを扱っています。そのため、big-O分析の適用は、用語の定義方法に(主に?)大きく依存します。

たとえば、一般的に出力を印刷することを意味し、妥当な量のデータがまったく同じ期間に印刷される/されるように、長時間待機することを意味します。また、非常に遠くまで行くには、やや珍しい(完全に間違っていなければ)定義の方法でもう少し追加する必要があります。特に、通常、ビッグO分析は、特定のタスク(ただし、CPUの使用/実行された操作だけでなく、メモリの使用などの観点から複雑さも考慮できることに注意してください)。

基本的な操作の数は、通常、かかる時間にかなり近くなります。そのため、2つを同義として扱うことは、それほど大きな範囲ではありません。しかし、残念ながら、それでも他の部分に行き詰まっています。処理されるデータの量は無制限に増加しています。その場合、課すことができる固定遅延は実際には機能しません。O(1)をO(N)と同等にするには、無限の遅延を課して、固定量のデータを印刷するのに、無限量のデータと同じように永久にかかるようにする必要があります。


10

何に関連してbig-O?

あなたはそれtwentyYearsLaterが「入力」であると直感的に思われます。確かにあなたがあなたの関数を

void helloWorld(int years) {
   // ...
}

それはO(N)で、N =年です(または単にと言いますO(years))。

私のアルゴリズムは、コード行でで始まる偶然に何を書いてもO(N)だと思いますtwentyYearsLater =。しかし、人々は通常、実際のソースコードの数字を入力として考慮しません。コマンドライン入力を入力と見なしたり、関数シグネチャ入力を入力と見なしたりする可能性がありますが、ほとんどの場合、ソースコード自体ではありません。それはあなたがあなたの友人と論争していることです-これは「インプット」ですか?直感的に入力のように見えるようにコードを設定し、プログラムの6行目のNに関して大きなO実行時間を確実に確認できますが、このようなデフォルト以外の選択を使用した場合入力として、あなたは本当にそれについて明示する必要があります。

ただし、コマンドラインや関数への入力など、より一般的な入力にすると、出力はまったくなく、関数はO(1)になります。20年かかりますが、big-Oは定数倍まで変化しないため、O(1)= O(20年)です。

同様の質問-ランタイムは何ですか:

void sortArrayOfSizeTenMillion(int[] array)

それが言うことを実行し、入力が有効であり、アルゴリズムがクイックソートまたはバブルソートまたは適切なものを利用していると仮定すると、それはO(1)です。


入力をハードコーディングしても、入力が消えるわけではありません。また、どのような場合でもO(1)時間の複雑さのクイックソートとバブルソートはありません。bigocheatsheet.com
Theo Brinkman

@TheoBrinkman技術的になりたい場合、チューリングマシンモデルで、入力について考えていることをチューリングマシン自体にエンコードすると、定義では、入力ではなくなります。その後、チューリングマシンは、実際の入力に関係なく、一定の時間で実行されます。何らかの意味で「バブルソート」を実行しないのは、ある意味ではなく、独自の表現で動作するためですが、非技術的な用語では、アルゴリズムをバブルソートとして説明できます。
djechlin

同様に「非技術的な用語」で、問題のアルゴリズムを吊り橋として説明できます。
Theo Brinkman、2015

@TheoBrinkmanいいえ、できませんでした。それは誰にとっても意味がありません。
djechlin

それは、それをO(1)バブルソートとして説明するのと同じくらい意味があります。
Theo Brinkman、2015

8

この「アルゴリズム」は、O(1)または一定時間として正しく記述されています。このプログラムへの入力がないため、Big Ohの観点から分析するNがないと主張されています。入力がないことに同意しません。これを実行可能ファイルにコンパイルして呼び出すと、ユーザーは任意の長さの入力を指定できます。その入力長はNです。

プログラムは入力を無視します(長さは問わない)。したがって、所要時間(または実行される機械語命令の数)は、入力の長さに関係なく(固定環境=開始時間+ハードウェア)、同じであるため、O(1 )。


ただし、開始時間とハードウェアが同じであっても、操作の数は必ずしも一定ではありません。その上、O(1)アルゴリズムを主張するには、出力は常に一定である必要があり、一定ではありません。開始時間とハードウェアに基づいて大きく変動します。また、非常に簡単に無限になる可能性もあり、一定ではありません。定義した入力と実行された操作の数の間に関係はありません。それは一定ではなく、単に定義されていません。有限数を指定することはできず、常にそれよりも操作が少なくなることを知っています。
サービー

最長時間は20年です。私たちが将来それを始めるならば、はい、それはより長くかかります。ループの反復にかかる時間には有限の下限があり、シリアルハードウェアで実行していると仮定しましょう。次に、ループの実行回数を制限できます。つまり、無視された入力のサイズに関係なく、計算全体を定数関数で制限できます。
waldol1

Let's suppose that there is a finite lower bound on the amount of time a loop iteration takesそれは誤った仮定です。プログラムは永久に実行できます。私がしなければならないのは、システムクロックを今から50年後に設定して開始することだけです。または、時計を前に進めるよりも速く戻し続けるか、過去の不確定なポイントから開始することもできます。プログラムの実行時間に下限があると思い込むことはできません。永久に実行できます。ただし、(偽の)仮定を真としても、実行された操作の数を入力に関連付けることはできません。
サービー

1回のループ反復には有限の時間がかかります。無限に実行することは可能かもしれませんが、それぞれはおおよそ一定でなければなりません。その仮定に問題はありません。
waldol1

その[完全に正しくない]ロジックにより、すべてのアルゴリズムは常に O(1)になります。これは、個々の操作が常に一定であるためです。あなたは単にビッグオーが何であるかを知らないことを単に示しているだけです。これは、入力のサイズと実行された関連する操作の数の間の関係を(コンテキストで)記述するためのツールです。O(1)は、入力に関係なく実行される操作の数が一定であることを意味します。ここで、入力に関係なく実行される操作の数は一定ではありません。実行される可能性のある操作は無限であり、!=定数は無限です。
サービー

6

私が驚いたことの1つはまだ言及されていません:big-O表記は上限です!

誰もが気づいた問題は、アルゴリズムへの入力を表すNがないため、big-O分析を行う必要がないことです。ただし、これは、int n「Hello World」のn時刻を受け入れて印刷するなどの基本的なトリックで簡単に軽減できます。それはその苦情を回避し、そのDateTime怪物がどのように機能するかという本当の問題に戻るでしょう。

whileループが終了するという実際の保証はありません。私たちは、それが時に持っていると思うしたいといくつかの時間が、それを検討DateTime.now戻り、システムの日付と時刻。これが単調に増加しているという保証は実際にはありません。病理学的に訓練されたサルが2015年10月21日12:00:00 UTCにシステムの日付と時刻を常に変更し、誰かがサルに自動フィットシューズとホバーボードを渡すまで、それが存在する可能性があります。このループは実際には無限の時間実行できます!

あなたが実際にbig-O表記の数学的定義を掘り下げるとき、それらは上限です。彼らは最悪のシナリオを示しています。ここでの最悪のケース*のシナリオは無限のランタイムであるため、このアルゴリズムのランタイムの複雑さを表すbig-O表記がないことを宣言する必要があります。 1/0が存在しないのと同じように、存在しません。

*編集:KTとの話し合いから、big-O表記でモデル化しているシナリオが最悪のケースであると推定することが常に有効であるとは限りません。ほとんどの場合、個人が使用しているケースを特定できない場合、彼らは最悪のケースを調査することを意図していました。ただし、最適なランタイムでBig-Oの複雑度分析を実行できます。


2
実際、Oはある意味で「上限」ですが、O表記法を使用して「最悪の場合の複雑さ」についてのみ説明できるという意味ではありません。予想される複雑さ、最良の場合の複雑さ、その他の機能的特性-それらすべては、O境界の観点から議論できます。
KT。

@KYの最良の場合の複雑さはリトルオーと呼ばれ、予想される複雑さはビッグシータです。big-oは、その数学的定義により、常に最悪の場合の複雑さです。
Cort Ammon

いいえ、あなたはここで間違っています。定義を再確認してください。
KT。

@KTわかりました。再確認します。あなたもそれらを再確認します。en.wikipedia.org/wiki/Big_O_notationそのアンダーファミリーのバッハマン-ランダウ記法
Cort Ammon

私はあなたが関数fを取り、関数がとg同じであると宣言するような非常識なことをすることができると思いますがf、制限されたドメインではfの最良のケースのみを含み、次にbig-ohをオンgにしますが、そうすると縮退したように聞こえますそれ。
Cort Ammon、2015

5

複雑さは、時間/空間の観点から計算「馬力」を測定するために使用されます。Big O表記を使用して、「計算可能」または「計算不可能」の問題を比較し、どのソリューション(アルゴリズム)が他のソリューションより優れているかを比較します。そのため、任意のアルゴリズムを2つのカテゴリに分類できます。多項式時間で解けるものと解けないものです。

ErathosteneのSieveのような問題はO(n ^ exp)であり、nの小さな値で解決できます。それらは計算可能であり、多項式時間(NP)ではないため、特定の数値が素数であるかどうかを尋ねられた場合、答えはそのような数値の大きさによって異なります。さらに、複雑さはハードウェアに依存しないため、より高速なコンピューターを使用しても何も変わりません...

Hello Worldはアルゴリズムではないため、その複雑さを判断しようとしても意味がありません。単純なアルゴリズムは次のようなものです。乱数を指定して、偶数か奇数かを判断します。さて、与えられた数が500桁であることは重要ですか?いいえ、最後の桁が偶数か奇数かを確認する必要があるだけです。より複雑なアルゴリズムは、特定の数値が3で割り切れるかどうかを判断することです。一部の数値は「簡単」に計算できますが、「難しい」ものもあります。これは、その大きさのためです。次の間に残りを決定するのにかかる時間を比較します1桁の数字と500桁の数字。

より複雑なケースは、テキストをデコードすることです。復号化キーを持っている人にメッセージを伝えていることもわかっている、ランダムなシンボルの配列があります。送信者が左側のキーを使用し、Hello WorldがGwkki Qieksと読んだとします。「ビッグハンマー、ノーブレイン」ソリューションは、これらの文字のすべての組み合わせを生成します。AaaaからZzzzまでの単語辞書を検索して、有効な単語を特定し、2つの共通文字(i、k)を共有します。同じ位置。この変換関数はBig Oが測定するものです。


4

ほとんどの人は2つの非常に重要なことを見逃しているようです。

  1. プログラムに入力があります。これは、システム時刻が比較されるハードコーディングされた日付/時刻です。入力はアルゴリズムを実行する人の制御下にあり、システム時間はそうではありません。このプログラムを実行している人が制御できる唯一のことは、比較にハードコードした日付/時刻です。

  2. プログラムは入力値に基づいて変化しますが、入力セットのサイズには影響しません。これは、big-O表記が関係しているものです。

したがって、これは不確定であり、このプログラムに最適な「big-O」表記はおそらくO(null)またはおそらくO(NaN)です。


1
(2)完全に間違っている。通常、「入力の長さ」が考慮されます。固定サイズのオブジェクト(整数など)のリストまたは配列の場合、実際にはセットのサイズになります。1395195191600333のような数値を因数分解するには、それはその2進数(または10進数など)表現の長さ、つまり桁数になります。すでに述べたように、(2)での定義では、big-Oを使用して「findPrimeFactors(int num)」の複雑さを議論することを禁止しています。
djechlin

4

Nを定義しないと誰もが正しく指摘しましたが、答えは最も合理的な解釈の下にありません。場合Nは、私たちが印刷している文字列の長さである「こんにちは、世界!」これは単なる例であり、「for」というアルゴリズムとしてこれの説明から推測できるようにhello, world!、アルゴリズムはO(N)です。これは、印刷に30、40、または50年かかる出力文字列があり、それに一定の時間だけを追加しています。O(kN + c)∈O(N)。

補遺:

驚いたことに、誰かがこれに異議を唱えています。ビッグOとビッグofの定義を思い出してください。一定の時間cだけ待ってから、長さNのメッセージを線形時間で出力するアルゴリズムがあるとします。(これは元のコードサンプルを一般化したものです。)印刷を開始するのに20年かかると、1兆文字の印刷にはさらに20年かかると任意に言いましょう。してみましょうC = 20及びK = 1012、例えば、任意の正の実数を行います。これは、文字あたりd = c / k(この場合は2×10⁻¹¹)年の比率であるため、実行時間fN)は漸近的にdN + c年。N > kのときは常に、dN = c / k N > cです。したがって、すべてのN > kに対してdN < dN + c = fN)<2 dNであり、fN)∈Θ(N)です。 QED


N = 13の場合
djechlin

しかし、「Hello world」だけでなく、不明な数の「まだ時間ではありません」という行も出力します。また、Big Oは、入力のサイズと出力のサイズを比較するために実際に使用されるのではなく、入力のサイズを操作の数または使用されるメモリの量と比較するために一般的に使用されます。
サービー

@Servy一定のメモリですが、実行時間を暗黙的に制限していました。出力のサイズもO(N)であり、任意の文字列の場合、20年間の待機メッセージと比較しても、その時間に印刷される文字列は任意に大きくなる可能性があります。
Davislor

@Servy私は明確にするために編集しました、いいえ、ここではNは出力のサイズではありません。どのようにその印象を与えたかはわかりませんが、あいまいさは取り除きます。
Davislor

1
したがって、プログラムが入力を受け取ると想定すると、受け取らない場合、出力は任意に大きくなる可能性があり、できない場合、ループは何も行わない場合、および場合によっては出力が関連します。入力、そうでなければ、はい、プログラムは線形です。もちろん、これらの仮定のすべて1つが完全に偽であるため、それらから引き出されたという結論は成立しません。あなたが誤った仮定をすることなくあなたのポイントを示すことができれば、それは何かを意味するでしょう。
サービー

4

コードが従来のアルゴリズムのように見えないので、人々は捨てられていると思います。以下は、より整形式であるが、OPの質問の精神に忠実であるコードの翻訳です。

void TrolloWorld(long currentUnixTime, long loopsPerMs){
    long laterUnixTime = 2051222400000;  //unix time of 01/01/2035, 00:00:00
    long numLoops = (laterUnixTime-currentUnixTime)*loopsPerMs;

    for (long i=0; i<numLoops; i++){
        print ("It's still not time to print the hello …");
    }
    print("Hello, World!");
}

入力は明示的ですが、以前はコードが開始された時間とコードを実行しているハードウェアの速度によって暗黙的に指定されていました。コードは確定的であり、指定された入力に対して明確に定義された出力を持っています。

提供できる入力に課せられる制限のため、実行される操作の数には上限があるため、このアルゴリズムは実際にはO(1)です。


2

この時点で、はい

このアルゴリズムには暗黙の入力、つまりプログラムの開始時刻があります。実行時間は、いつ開始されるかに応じて線形に1で変化します。2035年以降、whileループは直ちに終了し、プログラムは定数演算2の後で終了します。したがって、ランタイムはO(max(2035 - start year, 1))3と言えます。ただし、開始年には最小値があるため、アルゴリズムの実行に20年以上かかることはありません(つまり、定数値)。

4を定義することで、意図に沿ったアルゴリズムを作成できます。DateTime TwentyYearsLater = DateTime.Now + new TimeSpan(365*20,0,0,0);

1これは、時間単位あたりの操作の最大数があるため、操作数として測定される実行時間のより技術的な意味に当てはまります。
2フェッチDateTime.Nowが一定の操作であると仮定すると、これは合理的です。
3これはに関して減少関数であるためstart year、ここでは大きなO表記を多少乱用していますが、で表現することでこれを簡単に修正できますyears prior to 2035
4次に、アルゴリズムは開始時間の暗黙的な入力に依存しなくなりましたが、それは重要ではありません。


1

これはO(n)だと私は主張します。参照としてhttp://www.cforcoding.com/2009/07/plain-english-explanation-of-big-o.htmlを使用します

ビッグオーとは?

ビッグO表記は、キーファクターが無限大に向かう傾向がある場合に、成長率をキーファクターまで下げることにより、アルゴリズムの相対的な複雑さを説明しようとします。

そして

Big-Oの最も良い例は、算術演算です。学校で学んだ基本的な算術演算は次のとおりです。

添加; 減算; 乗算; そして分割。これらはそれぞれ操作または問題です。これらを解く方法をアルゴリズムと呼びます。

あなたの例では、

n = 20(単位は年)の入力が与えられます。

アルゴリズムは数学関数f()です。ここで、f()はたまたまn年間待機し、その間に「デバッグ」文字列があります。スケール係数は1です。このスケール係数を変更することにより、f()を増減できます。

この場合、出力も20です(入力を変更すると、出力が線形に変更されます)。

基本的に機能は

f(n) = n*1 = n
    if  n = 20, then 
f(20) = 20 
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.