Last active
August 29, 2015 13:57
-
-
Save MishaelRosenthal/9785126 to your computer and use it in GitHub Desktop.
Binary search on a sorted array
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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