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

1,175 views

Published on

社内勉強会でO(logN)とかをわかり易く説明しました

Published in: Software
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,175
On SlideShare
0
From Embeds
0
Number of Embeds
470
Actions
Shares
0
Downloads
2
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

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

  1. 1. 計算量のはなし 株式会社SRA 阪井 誠 <sakai @ sra.co.jp>
  2. 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. 最大値の計算量 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. 最大値の計算量 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. バブルソートの計算量 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. バイナリツリー 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. 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. 計算量の比較 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. まとめと気を付けること 9 • O(1) < O(logN) < O(N) < O(N2) < O(N3) – O(NlogN)はどこでしょう? • 計算量の少ない処理を使う方が良い • ただし、呼び出しにN回ループを使っていると O(logN)はO(NlogN)となりO(N)より大きくなる • 全体の構造を意識してプログラムを設計しな いといけない
  10. 10. おまけ1:O(1)のデータ構造/アルゴリズム例 10 • 配列(固定長)のn番目のデータの取出し – データサイズ×nでアドレスが求まる • 双方向リスト(可変長)の最初と最後の取出し – 先頭と最後を覚えておけば直接アクセスできる(スタック、キューなど) – N番目は先頭からn個追わないといけない • ハッシュ – 与えられたキーからハッシュ関数でアドレスを決める – ハッシュ=メチャメチャに切る(例:ハッシュドビーフ) ハッシュ 関数
  11. 11. おまけ2:計算量の応用分野 • ビッグデータ – 計算量の少ないアルゴリズムを用いて、大量デー タを効率よく扱う • 暗号 – 素因数分解など、計算量の多い難しい問題を利 用して強い暗号を作る • 人工知能 – 計算量の多いアルゴリズムはあきらめて、簡便な 方法を探す
  12. 12. ナップサック問題と グリーディーアルゴリズム 12 ポテト チップ ポテト チップ • 最適な答えを得るのは難しい • 大きなものから詰め込むと効率が良い => 「優先度の高いものから実施せよ!」 (ゲームで用いられるα・β法にもつながる考え)
  13. 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) の遅さです。高速なランダムアクセスが必要ならリストを使ってください。

×