$30 off During Our Annual Pro Sale. View Details »
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
みんなで書こう二分探索
Search
matumoto
June 10, 2021
Technology
0
68
みんなで書こう二分探索
2021/7月の大LTでの発表資料です
イベントページはこちら
https://zli.connpass.com/event/216615/
matumoto
June 10, 2021
Tweet
Share
More Decks by matumoto
See All by matumoto
testingを眺める
matumoto
1
170
sync/v2 プロポーザルの 背景と sync.Pool について
matumoto
0
520
Goトランザクション処理
matumoto
1
53
いまいちどスライスの 挙動を見直してみる
matumoto
0
360
Go1.22のリリース予定の機能を見る
matumoto
0
69
GoのUnderlying typeについて
matumoto
0
210
Typed-nilについて
matumoto
0
340
GoのType Setsという概念
matumoto
0
32
GoのRateLimit処理の実装
matumoto
0
420
Other Decks in Technology
See All in Technology
Active Directory 勉強会 第 6 回目 Active Directory セキュリティについて学ぶ回
eurekaberry
16
5.9k
Claude Code はじめてガイド -1時間で学べるAI駆動開発の基本と実践-
oikon48
41
24k
OpenShiftのBGPサポート - MetalLB+FRR-k8s編
orimanabu
0
150
ブラウザ拡張のセキュリティの話 / Browser Extension Security
flatt_security
0
250
経営から紐解くデータマネジメント
pacocat
9
1.9k
知っていると得する!Movable Type 9 の新機能を徹底解説
masakah
0
200
私のRails開発環境
yahonda
0
180
AI/MLのマルチテナント基盤を支えるコンテナ技術
pfn
PRO
4
680
Excelデータ分析で学ぶディメンショナルモデリング ~アジャイルデータモデリングへ向けて~ by @Kazaneya_PR / 20251126
kazaneya
PRO
3
840
Ryzen NPUにおけるAI Engineプログラミング
anjn
0
180
GitLab Duo Agent Platformで実現する“AI駆動・継続的サービス開発”と最新情報のアップデート
jeffi7
0
110
その設計、 本当に価値を生んでますか?
shimomura
2
160
Featured
See All Featured
Thoughts on Productivity
jonyablonski
73
5k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.1k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
51k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
54k
GraphQLとの向き合い方2022年版
quramy
49
14k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
960
Imperfection Machines: The Place of Print at Facebook
scottboms
269
13k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.6k
Large-scale JavaScript Application Architecture
addyosmani
514
110k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
Building Adaptive Systems
keathley
44
2.9k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
31
2.7k
Transcript
みんなで書こう二分探索 会津大学2年松本響輝
二分探索って? ・二分していく探索です それ以上でもそれ以下でもない 探索する区間の長さをNとして なんと計算量オーダーがO(logN)ではやい! 半分,半分,半分,半分,......................
強い方のツイートで一時期盛り上がりました
どういう動き方か
どう動くの? 端っこを決めて、その真ん中で区間を分けていく。 使う方 使う方 使う方
なにを求められるのか
なにができるの ・ある境界を求められる 例 A = {3, 5, 10, 20, 33,
90, 98}の配列で値が15以上を満たす最小の index を返す場合 left : 0 right : 6 mid : 3 ← ( left + right ) / 2 A mid は20なので、15以上! ということは、探索する区間を左側にずらす→ right を mid にする
A = {3, 5, 10, 20, 33, 90, 98}の配列で値が15以上を満たす最小の index
を返す場合 left : 0 right : 3 ← mid mid : 1 ← ( left + right ) / 2 A mid は5なので、15以上じゃない! ということは、探索する区間を右側にずらす→ left を mid + 1にする
A = {3, 5, 10, 20, 33, 90, 98}の配列で値が15以上を満たす最小の index
を返す場合 left : 2 ← mid + 1 right : 3 mid : 2 ← ( left + right ) / 2 A mid は10なので、15以上! ということは、探索する区間を右側にずらす→ left を mid + 1にする
A = {3, 5, 10, 20, 33, 90, 98}の配列で値が15以上を満たす最小の index
を返す場合 left : 3 ← mid + 1 right : 3 mid : 3 ← ( left + right ) / 2 A mid は20なので、15以上! left と right が同じになったので left を返す( right でもよい)
なにを求めるの? ・ある境界を求められる つまり、条件を定めたときの境界を求めることができる ・ソート済みの配列の中で値が10以上を満たす最小の index ・0~n以下の素数の中で200000以上の最小の素数 条件が有効でない部分 条件が有効な部分 ※境界は整数でないこともあります
なにがうれしいのか
なにがうれしい? ・応用ができる! 例:値の検索 配列の中で値が x 以上を満たす最小の index → index 番目が
x ならOK、そうでないならその配列にはない ・計算量が少ない! 最悪でも計算量がO(logN) 0~1018くらいの区間だったとしても十分に高速(そんな大きい数を扱う職場...)
None
実装は? 1. 二分探索を使わない 2. 標準の関数を使う 3. 自分で作る
1.二分探索を使わない
1.二分探索を使わない (´・ω・`) え?
2.標準の関数を使う
2.標準の関数を使う • C++ ◦ lower_bound ◦ upper_bound • Python ◦
bisect • java ◦ Arrays.binarySearch ただ、配列に対して二分探索はできるが それ以外への二分探索ができない...
3.自分で作る
3.自分で作る(C++) 関数にするより、テンプレを覚えて書いた方が汎用性がよい! そんなあなたにめぐる式二分探索! ※競技プログラミング界隈はキャラがおおいがち 因幡めぐるアカウント様( https://twitter.com/meguru_comp)より
めぐる式二分探索の前に.. ・二分探索の実装上の工夫(先人たちの汗と涙の知恵) • 区間は半開区間[ left, right )で扱う 閉区間[ left, right
] これは left 以上 right 以下 半開区間 [ left, right ) これは left 以上 right 未満 今まで [ left, right ] → [ left, mid - 1 ]だったが [ left, right ) → [ left, mid )と簡潔に! ※ left を mid にする場合もおなじ ついでに、長さが N の配列のとき [ 0, N - 1 ] としてたのが [ 0, N ) にできる
めぐる式二分探索とは • めぐる式二分探索の特徴 ・ループの条件に絶対値を使っている ・ok, ng などの変数がある ・半開区間 ・最終的には ok
に求めたい値が入っている ・判定部分を関数にしている(←これについては諸説ありです) (ok, ng 以外の変数名の候補としては valid, invalid がある)
valid, invalid(ok, ng)みたいな変数には何の値が入るの? • ある条件を元にその境界を求めたい→二分探索でのis_valid関数を作る • validにはis_valid(valid)としたときに必ずtrueとなる値を入れる • invalidにはis_valid(invalid)としたときに必ずfalseとなる値を入れる •
例 ◦ n要素のソート済み配列 aからx以上の要素の最小のインデックスを見つけたい ▪ (配列aにはx以上の要素が少なくとも 1つは存在するものとする ) ◦ is_valid関数はindexを受け取ってa[i] >= x かどうかを判定するように作る ◦ validの初期値にはn-1を入れておく ◦ invalidの初期値には-1を入れておく(今回は invalidが開区間なので0じゃない) ◦ これであとは二分探索するだけ ▪ ※実際には、配列aの末尾に番兵として INFを挿入してvalid=nとする方が多いと思います
閉区間の実装と比較 ・+1, -1 を考えるのが混乱させる ・left か right のどちらにほしい値があるのか考える必要がある
閉区間の実装と比較 ・is_valid 関数を作ると、条件だけ考えることができる ・最終的にほしい値が valid だと分かりやすい ←の is_valid 関数は C++
のラムダ式です
これであなたも快適な二分探索ライフを! ご清聴ありがとうございました