アルゴリズムとデータ構造のコースをたどっています。
今日、私の教授は、次のアルゴリズムの複雑さは_2^n
_であると述べました。
レッスンが終わるまで待って、彼に近づいて、それがO(n)
アルゴリズムだと実際に信じていると言ったので、それを証明するために計算をして、見せたかったのですが、彼は言い続けました。それは、私に説得力のある説明を与えずに、そうではありませんでした。
アルゴリズムは再帰的であり、その漸化式は次のとおりです。
_ { 1 if n=1
T(n) = {
{ 2T(n/2) otherwise
_
私はそれを次のようにO(n)
と計算しました。
T(n)
を展開してみましょう
_T(n) = 2 [2 * T(n/(2^2))]
= 2^2 * T(n/(2^2))
= 2^2 * [2 * T(n/(2^3))]
= 2^3 * T(n/(2^3))
= ...
= 2^i * T(n/(2^i)).
_
T内の項が1になると停止します。つまり、次のようになります。
n/(2^i) = 1 ==> n = 2^i ==> i = log n
置換後、
_T(n) = 2^log n * T(1)
= n * 1
= O(n).
_
このアルゴリズムはマージソートのレッスンから飛び出したので、O(n log n)
で有名なマージソートの複雑さが2T(n/2)+ theta(n)(明らかにメジャー、次に2T(n)であることに気付きました。/2))、そして私は彼になぜそれが低い複雑さのアルゴリズムがより高いbig-Oを得るのかと尋ねました。なぜなら、この時点では、私にとっては直感に反しているからです。彼は一言一句、「それが直感に反すると思うなら、あなたはあなたの数学に深刻な問題を抱えている」と答えた。
私の質問は次のとおりです。
まず最初に、単純な再帰的アルゴリズムの複雑さを分析するために、最初のストップは マスター定理 であり、式T(n) = 2·T(n/2)
をスキーマT(n) = a·T(n/b) + f(n)
。係数を比較すると、定数x
のa = 2, b = 2, f(n) = x
がわかります。マスター定理は、係数間の特定の関係が成り立つかどうかに応じて、複雑さを与えます。
ここでは、f(n) = O(n^c)
およびc < log_b a
のようなc
が存在し、c = 0
(f(n) = O(1) = O(n^0)
および0 < log_2 2 <=> 0 < 1
)がある場合に適用されます。したがって、マスター定理はT(n) = Theta(n^(log_b a)) = Theta(n)
を示しているので、T(n) = O(n)
も成り立ちます。つまり、あなたは正しいです。
あなたの証明はチェックアウトしますが、本当に納得させるためには、帰納法による証明を使用する必要があります。基本的に誘導を使用しましたが、各ステップに明確なラベルを付けていないため、従うのが少し難しくなります(そして、逆方向に実行しました。基本ケースT(1)
から始めて、プロパティが一般的なケースから始めて基本ケースに向かって進むのではなく、任意のn
に対してT(n+1)
を保持します。
「アルゴリズムは再帰的であり、この複雑さがあります:...」
あなたの質問の定式化から、関数T(n)
は分析されるアルゴリズムではなく、その複雑さであるように思われます。あなたの証明では、実際、関数T
が指数関数として漸近的に振る舞うことを示しています。
それから、あなたが間違ったことを証明しようとしているのではないかという誤りかもしれません。言い換えると:
T
の計算には線形時間がかかるのは正しいです(おそらくもっと短い、私が推測する対数時間)。T
で表される元のアルゴリズムの複雑さは指数関数的であると言っているのは正しいです。アルゴリズムの実行時間はO((log n)^ 2)になります。これは、nビットの数を2倍にするlognステップがあるためです。結果はO(n)です。 n/2がフロア(n/2)を意味すると仮定すると、完全な帰納法によってT(n)≤nであることが簡単に示されます。
直感的には、T(n)= O(2 ^ n)の場合、T(1000)は約2 ^ 1000になります。しかし、T(1000)= 2 * T(500)は、約2 ^ 501になるはずです...わずかな違い。
もちろん、Big-Oの定義によるとn = O(2 ^ n)です。
あなたの教授の言うことがあまりにも的外れであるならば、おそらく再帰が実際にここに正しく投稿されていないのではないかと思うかもしれません。