Scala algorithm: Binary search in a rotated sorted array
Published
Algorithm goal
This is a variation of BinarySearch, where the input array is rotated (RotateArrayRight).
For example, an input of [1,2,3,4], rotated could become [3,4,1,2].
Binary search runs in \(O(\log{n})\), which is faster than a linear search (\(O(n)\)).
Test cases in Scala
assert(searchIn(Array.empty, 7) == None)
assert(searchIn(Array(7, 1), 7) == Some(0))
assert(searchIn(Array(9, 1, 7), 7) == Some(2))
assert(searchIn(Array(7, 9, 1), 7) == Some(0))
assert(searchIn(Array(6, 7, 8, 9, 1, 2, 3, 4, 5), 7) == Some(1))
assert(searchIn(Array(6, 7, 8, 9, 1, 2, 3, 4, 5), 1) == Some(4))
assert(searchIn(Array(6, 7, 8, 9, 1, 2, 3, 4, 5), 10) == None)
assert(searchIn(Array(6, 7, 8, 9, 1, 2, 3, 4, 5), 9) == Some(3))
assert(searchIn(Array(6, 7, 8, 9, 1, 2, 3, 4, 5), 4) == Some(7))
assert(searchIn(Array(6, 7, 8, 9, 1, 2, 3, 5), 5) == Some(7))
Algorithm in Scala
20 lines of Scala (compatible versions 2.13 & 3.0), showing how concise Scala can be!
Explanation
The Scala implementation uses the Range concept in order to achieve a more terse solution, in particular by defining the range for the next iteration in terms of the previous range, rather than dealing with raw indices.
This is a very powerful concept because you notice that in Scala, algorithms can be quite self-explanatory whereas in some C/Python algorithm implementations one would have to refer to documentation and comments for an explanation. Documentability is crucial in sharing knowledge. (this is © from www.scala-algorithms.com)
The variation requires us to capture the case where our range is still uneven. In this case, the code explains the story
Scala concepts & Hints
Def Inside Def
A great aspect of Scala is being able to declare functions inside functions, making it possible to reduce repetition.
It is also frequently used in combination with Tail Recursion.
Option Type
The 'Option' type is used to describe a computation that either has a result or does not. In Scala, you can 'chain' Option processing, combine with lists and other data structures. For example, you can also turn a pattern-match into a function that return an Option, and vice-versa!
Range
The
(1 to n)
syntax produces a "Range" which is a representation of a sequence of numbers.Stack Safety
Stack safety is present where a function cannot crash due to overflowing the limit of number of recursive calls.
This function will work for n = 5, but will not work for n = 2000 (crash with java.lang.StackOverflowError) - however there is a way to fix it :-)
In Scala Algorithms, we try to write the algorithms in a stack-safe way, where possible, so that when you use the algorithms, they will not crash on large inputs. However, stack-safe implementations are often more complex, and in some cases, overly complex, for the task at hand.
Tail Recursion
In Scala, tail recursion enables you to rewrite a mutable structure such as a while-loop, into an immutable algorithm.