社内勉強会で二分探索法を書いてみた話
社内勉強会で二分探索法を書いてみた話:
今回は二分探索法によるサーチプログラムを書くという課題を若手社員と一緒にもくもく書いてみました。
ネット検索については答えそのものを調べない(コピペ/写経禁止)という制限の下OKとしました。
1〜1000までの数値が順番に格納された配列Aから、任意の値Bを二分探索で取り出す
今回は二分探索法を使うという前提がある為、全員が同じ方針でプログラムを書くことになりました。
簡単に二分探索法の手順を示すと下記の通りです。
今回もまずこの2種類の書き方が出てきました。
基本方針は前回記事と同じなのでご参照ください。
社内勉強会で比率計算を書いてみた話
ただし、今回は配列からの探索なので、実際に活用してみようと考えると配列のデータ数の上限は必ずしも決まっていないと思います。
実案件で利用してみようと思うのであれば、ループを使う方がより安心です。
探索を進める方法としてはこの2種類の方法が出てきました。
文字での説明は難しいのでコードを載せます。
それぞれこんな感じでしょうか。
whileの条件次第でdo-whileじゃなくてもよくなります。
見た目上は大した差はなく、お好みでということになりそうですが、配列操作は重い処理になるので避けた方が良いです。
以下は今回の問題を各言語で書いてもらったものを比較しやすいように書き換えたコードです。
上に記した通り、配列のインデックスを使い、ループで回しています。
今回はSwiftの参加者がいなかったのでSwiftはお休みです。
はじめに
今回は二分探索法によるサーチプログラムを書くという課題を若手社員と一緒にもくもく書いてみました。ネット検索については答えそのものを調べない(コピペ/写経禁止)という制限の下OKとしました。
問題
1〜1000までの数値が順番に格納された配列Aから、任意の値Bを二分探索で取り出す
解法
今回は二分探索法を使うという前提がある為、全員が同じ方針でプログラムを書くことになりました。簡単に二分探索法の手順を示すと下記の通りです。
- 配列の中央に格納された値を取り出して、目的の値と比較する
- 目的の値であれば返す
- 目的の値より大きければ中央より前を次の探索対象とする(1に戻る)
- 目的の値より小さければ中央より後ろを次の探索対象とする(1に戻る)
再帰 or ループ
今回もまずこの2種類の書き方が出てきました。基本方針は前回記事と同じなのでご参照ください。
社内勉強会で比率計算を書いてみた話
ただし、今回は配列からの探索なので、実際に活用してみようと考えると配列のデータ数の上限は必ずしも決まっていないと思います。
実案件で利用してみようと思うのであれば、ループを使う方がより安心です。
配列操作 or インデックス
探索を進める方法としてはこの2種類の方法が出てきました。文字での説明は難しいのでコードを載せます。
配列操作.kt
var centerVal: Int = 0
do{
val center: Int = list.size / 2
centerVal = list.get(center)
list = if(centerVal > target) {
list.dropLast(center)
}else {
list.drop(center)
}
}while(centerVal != target)
return centerVal
インデックス.kt
var centerVal: Int = 0
do{
val center: Int = (start + end) / 2
centerVal = list.get(center)
if(centerVal > target) {
end = center
continue
}
start = center
}while(centerVal != target)
return centerVal
whileの条件次第でdo-whileじゃなくてもよくなります。
見た目上は大した差はなく、お好みでということになりそうですが、配列操作は重い処理になるので避けた方が良いです。
コード例
以下は今回の問題を各言語で書いてもらったものを比較しやすいように書き換えたコードです。上に記した通り、配列のインデックスを使い、ループで回しています。
今回はSwiftの参加者がいなかったのでSwiftはお休みです。
Kotlin
fun main(args: Array<String>) {
val A = List<Int>(1000, { it + 1 })
val B = 233
println(binarySearch(A, B))
}
fun binarySearch(list: List<Int>, target: Int): Int{
if(target < list.first() || list.last() < target) {
return -1
}
var first = 0
var last = list.size
while(first + 1 != last) {
val center = (first + last) / 2
val centerVal = list.get(center)
if(centerVal == target) {
return centerVal
}
if(centerVal < target) {
first = center
}else {
last = center
}
}
return -1
}
PHP
<?php
function main() {
$A = range(1, 1000);
$B = 233;
echo binarySearch(A, B);
}
function binarySearch($list, $target)
{
if ($target < $list[0] || end($list) < $target) {
return -1;
}
$first = 0;
$last = count($list);
while($first + 1 !== $last) {
$center = floor(($first + $last) / 2);
$centerVal = $list[$center];
if($centerVal === $target) {
return $centerVal;
}
if($centerVal < $target) {
$first = $center;
}else {
$last = $center;
}
}
return -1;
}
main();
JavaScript
const main = () => {
const A = new Array(1000)
.fill('a')
.map((el, i) => i + 1)
const B = 233
console.log(binarySearch(A, B))
}
const binarySearch = (list, target) => {
let first = 0
let last = list.length
if(target < list[first] ||list[last-1] < target) {
return -1
}
while (first + 1 !== last) {
const center = Math.floor((first + last) / 2)
const centerVal = list[center]
console.log(first, center, last)
if (centerVal === target) {
return centerVal
}
if (centerVal < target) {
first = center
} else {
last = center
}
}
return -1
}
main()
Java
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
List<Integer> A = new ArrayList<Integer>() {
{
for(int i = 1; i <= 1000; i++) {
add(i);
}
}
};
int B = 233;
System.out.println(binarySearch(A, B));
}
private static int binarySearch(List<Integer> list, int target) {
int first = 0;
int last = list.size();
if(target < list.get(first) ||list.get(last - 1) < target) {
return -1;
}
while (first + 1 != last) {
final int center = (int) Math.floor((first + last) / 2);
final int centerVal = list.get(center);
if (centerVal == target) {
return centerVal;
}
if (centerVal < target) {
first = center;
} else {
last = center;
}
}
return -1;
}
}
まとめ
- 再帰よりループを使う
- 配列操作は重いのでインデックスを活用する
コメント
コメントを投稿