計算量の話
この記事は学ロボAdvent Calendar 2022の1日目の記事です。
魁はアドカレ作成者の私が務めさせて頂きます。
この記事ではプログラムの計算量などについて軽く軽く軽くおさらいします。
==============目次==============
===============================
0. はじめに
プログラムを書いた事がある人であれば、「計算量」や「漸近記法」の概念に一度は触れた事があると思います。
これらの概念はアルゴリズムを評価する際には欠かせない物であり、
ロボットなど、省メモリ/リアルタイム性が問われるソフトウェアの開発場面では、
常に計算量を意識してコーディングしているのでは無いでしょうか?
ですが、例えばの定義は?と聞かれると意外と怪しかったりするかもしれません。
この記事では、そういった基本的な概念のおさらいをしていく事を目指します。
ふと忘れてしまった時に思い出すキッカケに出来るような記事として使っていただければ幸いです。
1.計算量とは?
計算量というのは、雑に言うとアルゴリズムを実行する時に要する計算資源の事です。
計算量と呼ばれる物には以下の2種類があります。
・時間計算量 : アルゴリズムを実行するのに要するステップ数 (どのくらい手間がかかるか)
・空間計算量 : アルゴリズムを実行するのに要する記憶領域の量 (どのくらいメモリなどを食うか)
例えば時間計算量だったら、
問題のパラメータに依存しない最小限の処理を1ステップとして考えると分かり良いと思います。
「for文で1,2,...,nを足し合わせるのはnステップかかる」的な感じです。
勿論、問題のインスタンス毎に"具体的な"ステップ数や記憶量は変化するので、
「だいたいこれくらい」というのを表現するのに後述の漸近記法を用います。
2.漸近記法
まずはよく使われる記法の定義を記述します。
・
の時は、はの定数倍の範囲に限定されます。
ちなみにはの大文字です。
・
はによる(定数倍の範囲の)漸近的上界を与えます。
勿論が成立します。とかも成立するので雑に乱用できます。
・
はによる(定数倍の範囲の)漸近的下界を与えます。
※ 必要性に応じて、これらを使い分けるという話です。基本的に記法を用いるのが丸い様に感じます。
※ 実際、多くの本では記法を用いて計算量を評価している気がします。(個人の感想です。)
これらの記法は乱用すると非常に便利ですが、誤用すると怒られが発生するので注意しましょう。
他にもとか色々あるのですが、この記事ではここまでにしておきます。
3.具体例
ここからは幾つかのアルゴリズムを例に上げて計算量を考えていきます。
殆どの場合はとして問題無いとは思いますが、今回は書き分けています。
(そこの精度が要求される場面は稀だと思います。)
・3.1 クイックソート
クイックソートは非常に効率の良いソートアルゴリズムとして知られています。
GCCのsortではクイックソートの最悪ケースを改善したイントロソートが用いられています。
分割統治アルゴリズムの一種で、配列の右端をpivotとして選択し、
配列をpivotより大きい要素のみの部分列と小さい要素のみの部分列に入れ替え・分割する操作を
各部分列に繰り返し適用する事で、ソートを行うアルゴリズムです。
後述するマージソートと違って、均等に分割できるかで計算量が変化します。
最悪の場合は、分割時に長さの配列を長さの配列と長さの配列に分割した場合に対応します。
最良の場合は、均等に分割する場合に対応します。(後述のマージソートと同じ考え方で求められます。)
以上をまとめると、クイックソートの時間計算量は
・最悪計算量 :
・最良計算量 :
・平均計算量 :
となります。(詳細な計算は他の記事や本に任せます。)
直感的には最悪の場合は分割に掛かるので、を解く事で、
の時間計算量がかかる事が分かります。
・3.2 マージソート
マージソートも分割統治アルゴリズムの一種であり、詳細は省きますが、
配列を中央で2つの部分列に分割し、それぞれの部分列にソートを適用した物をマージする構造になっています。
一番好きなソートアルゴリズムです。
個人的にはクイックソートよりも直感的に何をやっているのかが把握しやすいと思います。
(実際は両方とも分割統治法に分類されるアルゴリズムで、全く同じ構造に従っています。)
分割操作は定数時間、マージ操作は配列の長さに対してで計算できるので、
このアルゴリズムの時間計算量は、元の配列の長さをとして、以下の様になります。
・最悪計算量 :
・最良計算量 :
・平均計算量 :
直感的には再帰木の深さがで、(毎回中央で分割するので基本的に2分木になります。)
各深さにおけるマージ処理のステップ数の総和はと考えられるのでになると計算できます。
※ 厳密には漸化式を解く事で求められます。
4.終わりに
実際のコーディング時には、オブジェクトのコピーにより計算量が意図せず増えていないかなどにも
注意して実装する必要があります。(vectorをコピーしててTLEした経験があります...。)
この記事は本当に軽くおさらいしただけなので、
計算量や漸近記法の概念がはじめましての人にはちょっと厳しいかもです。
取り敢えず漸近記法が適切に読めれば、大抵は困らないと思います。
不手際で急いで書いたので、間違いがあれば指摘して頂きたいです。
11月が31日まであると勘違いしてました...。
早晩加筆するかもです。
5.出典
・アルゴリズムクイックリファレンス
www.oreilly.co.jp
・アルゴリズムイントロダクション
鈍器。護身用にどうぞ。マージソートの計算量の証明などが載っています。
マスター定理の証明など、分割統治法についてもっと知りたい方はこちらの本をおすすめします。
www.kindaikagaku.co.jp