Skip to content

Instantly share code, notes, and snippets.

@MishaelRosenthal
Last active August 29, 2015 13:57
Show Gist options
  • Save MishaelRosenthal/9785126 to your computer and use it in GitHub Desktop.
Save MishaelRosenthal/9785126 to your computer and use it in GitHub Desktop.
Binary search on a sorted array
package com.liveperson.predictivedialer.examples.misc
import scala.math.Ordering
import scala.annotation.tailrec
/**
* Created with IntelliJ IDEA.
* User: mishaelr
* Date: 3/26/14
* Time: 2:47 PM
*/
object BinarySearch {
implicit class ArraysWithSearch[T](arr: Array[T])(implicit ord:Ordering[T]) {
/**
* Note: arr should be sorted!
* Time complexity is O(log n)
* @return arr.lastIndexWhere(_ <= value)
*/
def binarySearch(value: T) = {
@tailrec
def searchRec(start: Int, end:Int): Int = {
if(start > end)
end
else {
val middle = (start + end) / 2
if(ord.lteq(arr(middle), value))
searchRec(middle + 1, end)
else
searchRec(start, middle - 1)
}
}
searchRec(0, arr.length-1)
}
}
}
package com.liveperson.predictivedialer.examples.misc
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatest.FunSuite
import org.scalatest.prop.Checkers
import scala.util.Random
import org.scalacheck.Prop.BooleanOperators
/**
* Created with IntelliJ IDEA.
* User: mishaelr
* Date: 3/26/14
* Time: 3:05 PM
*/
@RunWith(classOf[JUnitRunner])
class BinarySearchTest extends FunSuite with Checkers{
import BinarySearch._
val rand = new Random(17)
test("find existing element") {
check{
(arr: Array[Double]) =>
(!arr.isEmpty) ==> {
val index = rand.nextInt(arr.length)
val sortedArr = arr.sorted
val expected = sortedArr.lastIndexWhere(_ <= sortedArr(index))
val actual = sortedArr.binarySearch(sortedArr(index))
println(s"expected $expected, actual $actual")
expected === actual
}
}
}
test("find general bound") {
check{
(arr: Array[Double]) =>
(!arr.isEmpty) ==> {
val sortedArr = arr.sorted
case class Range(min: Double, max: Double) {
def randFromRange = min + rand.nextDouble() * (max - min)
}
val range = Range(sortedArr.min-1, sortedArr.max+1)
val searchValue = range.randFromRange
val expected = sortedArr.lastIndexWhere(_ <= searchValue)
val actual = sortedArr.binarySearch(searchValue)
println(s"expected $expected, actual $actual")
expected === actual
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment