Advertisement

計算量のはなし(Redisを使うなら必読!O(logN)など)

Software Engineer at SRA
Oct. 2, 2015
Advertisement

More Related Content

Slideshows for you(20)

Viewers also liked(20)

Advertisement

More from Makoto SAKAI(20)

Advertisement

Recently uploaded(20)

計算量のはなし(Redisを使うなら必読!O(logN)など)

  1. 計算量のはなし 株式会社SRA 阪井 誠 <sakai @ sra.co.jp>
  2. (時間)計算量 2 • 最近こんな記述を見ませんか? • O(1) 、O(N) 、 O(logN)とはどんな処理? ソート済みセット型のコマンド(Redisマニュアル) ZADD(key, score, member) New in version 1.1. 計算時間: O(log(N)) Nはソート済みセット内の要素数 Deque: 両端における append や pop を高速に行えるリスト風のコンテナ(Python) Deque はどちらの側からも append と pop が可能で、スレッドセーフでメモリ効率が よく、どちらの方向からもおよそ O(1) のパフォーマンスで実行できます。 list オブジェクトでも同様の操作を実現できますが、これは高速な固定長の操作に特 化されており、内部のデータ表現形式のサイズと位置を両方変えるような pop(0) や insert(0, v) などの操作ではメモリ移動のために O(n) のコストを必要とします。 (その他の操作)両端についてインデックスアクセスは O(1) ですが、中央部分につい ては O(n) の遅さです。高速なランダムアクセスが必要ならリストを使ってください。
  3. 最大値の計算量 3 • 配列arrayにN個の正整数が入っています。 最大値を求めてください。 – 配列のサイズ:N – 配列のデータ:1,20,3,8,4,6,15,12,5,… – プログラム max=-1 indexをインクリメントして0~N-1まで繰り返す If max < array[index] max = array[index] ループは何回? データの追加の際のループは何回? 常にソートするとすれば、、
  4. 最大値の計算量 4 • 配列arrayにN個の正整数が入っています。 最大値を求めてください。 – 配列のサイズ:N – 配列のデータ:1,20,3,8,4,6,15,12,5,… – プログラム max=-1 indexをインクリメントして0~N-1まで繰り返す If max > array[index] max = array[index] ループは何回?N(時間計算量)・・・これをO(N)と書く データの追加の際のループは何回?1・・・O(1) 常にソートするなら?N(位置決め+ずらす)・・・O(N)
  5. バブルソートの計算量 5 • 配列arrayにN個の正整数が入っています。 バブルソートしてください。 – 配列のサイズ:N – 配列のデータ:1,20,3,8,4,6,15,12,5,… – プログラム indexをインクリメントして0~N-1まで繰り返す index2をインクリメントしてindex~N-1まで繰り返す If array[index] > array[index2] array[index] と array[index2]を入れ替える ループは何回?約N2回 ・・・ O(N2)
  6. バイナリツリー 6 • ソートデータを2分木で管理すると階層回で追加・検索 4 5 1 3 6 8 12 15 20 ノード数 ・・・1 (2の0乗) ・・・2 (2の1乗) ・・・4 (2の2乗) ・・・8 (2の3乗) ・・・16 (2の4乗) 8 9
  7. Logの定義 7 • A = logxN のとき xをA乗するとNになる • log28 は2を3乗すれば8(=2x2x2)なので3 • 情報系では2は省略してよいので log8 = 3 • 2分木は階層が深くなると葉が2倍に増える – 葉がN個なら深さはlogN • データの追加・検索はO(logN)で可能 – ソートにはN倍必要なのでO(NlogN)
  8. 計算量の比較 8一週間で身につくアルゴリズムとデータ構造 http://sevendays-study.com/algorithm/ • Nが1、1024、1メガ、1ギガの場合の計算量 • O(1): 1、1、1、1 • O(logN): 1、10、20、30 • O(N): 1、1,024、1,048,576、1,073,741,824 • 木構造の処理に10倍かかっても1、100、200、300
  9. まとめと気を付けること 9 • O(1) < O(logN) < O(N) < O(N2) < O(N3) – O(NlogN)はどこでしょう? • 計算量の少ない処理を使う方が良い • ただし、呼び出しにN回ループを使っていると O(logN)はO(NlogN)となりO(N)より大きくなる • 全体の構造を意識してプログラムを設計しな いといけない
  10. おまけ1:O(1)のデータ構造/アルゴリズム例 10 • 配列(固定長)のn番目のデータの取出し – データサイズ×nでアドレスが求まる • 双方向リスト(可変長)の最初と最後の取出し – 先頭と最後を覚えておけば直接アクセスできる(スタック、キューなど) – N番目は先頭からn個追わないといけない • ハッシュ – 与えられたキーからハッシュ関数でアドレスを決める – ハッシュ=メチャメチャに切る(例:ハッシュドビーフ) ハッシュ 関数
  11. おまけ2:計算量の応用分野 • ビッグデータ – 計算量の少ないアルゴリズムを用いて、大量デー タを効率よく扱う • 暗号 – 素因数分解など、計算量の多い難しい問題を利 用して強い暗号を作る • 人工知能 – 計算量の多いアルゴリズムはあきらめて、簡便な 方法を探す
  12. ナップサック問題と グリーディーアルゴリズム 12 ポテト チップ ポテト チップ • 最適な答えを得るのは難しい • 大きなものから詰め込むと効率が良い => 「優先度の高いものから実施せよ!」 (ゲームで用いられるα・β法にもつながる考え)
  13. 宿題 13 • それぞれのデータ構造/アルゴリズムを 考えてみましょう ソート済みセット型のコマンド(Redisマニュアル) ZADD(key, score, member) New in version 1.1. 計算時間: O(log(N)) Nはソート済みセット内の要素数 Deque: 両端における append や pop を高速に行えるリスト風のコンテナ(Python) Deque はどちらの側からも append と pop が可能で、スレッドセーフでメモリ効率が よく、どちらの方向からもおよそ O(1) のパフォーマンスで実行できます。 list オブジェクトでも同様の操作を実現できますが、これは高速な固定長の操作に特 化されており、内部のデータ表現形式のサイズと位置を両方変えるような pop(0) や insert(0, v) などの操作ではメモリ移動のために O(n) のコストを必要とします。 (その他の操作)両端についてインデックスアクセスは O(1) ですが、中央部分につい ては O(n) の遅さです。高速なランダムアクセスが必要ならリストを使ってください。
Advertisement