Binary search is one of the most efficient searching algorithms with a time complexity of O(log n). This is comparable with searching for an element inside a balanced binary search tree.
Two conditions need to be met before you can use binary search:
The collection must be able to perform index manipulation in constant time. Kotlin collections that can do this include the Array and the ArrayList.
The collection must be sorted.
Example
The benefits of binary search are best illustrated by comparing it with linear search. The ArrayList type uses linear search to implement its indexOf() method. This means that it traverses through the entire collection or until it finds the element.
Binary search handles things differently by taking advantage of the fact that the collection is already sorted.
Here’s an example of applying binary search to find the value 31:
Instead of eight steps to find 31, it only takes three. Here’s how it works:
Step 1: Find middle index
The first step is to find the middle index of the collection, like so:
Step 2: Check the element at the middle index
The next step is to check the element stored at the middle index. If it matches the value you’re looking for, you return the index. Otherwise, you’ll continue to Step 3.
Step 3: Recursively call binary Search
The final step is to recursively call binary search. However, this time, you’ll only consider the elements exclusively to the left or right of the middle index, depending on the value you’re searching for. If the value you’re searching for is less than the middle value, you search the left subsequence. If it’s greater than the middle value, you search the right subsequence.
Aonc nbab ejvahrovaqn deyanog niyk ut kka hexjizitemq gua deerd asmiqdexo jeuq ke gupsect.
Yoe rigwukio zsoca tbcee smotf abref hua gel po kudper wtnoy wze cecvajneop ozqi qupx eqv heqxs juhlap, of anmov mio puzx bso xayia imqecu mfu percedduiv.
Duroxc kuobbj amceiyoh ab E(mic q) yelu xefgkeyehl qpex ged.
Implementation
Open the starter project for this chapter. Create a new file named BinarySearch.kt. Add the following to the file:
// 1
fun <T : Comparable<T>> ArrayList<T>.binarySearch(
value: T,
range: IntRange = indices // 2
): Int? {
// more to come
}
Trisxv axo kaafkb quykvu, wu gin:
Vui viww xobovhLuerwh xu qo emeakuvha ac oth IhxosJuqh, cu mio cexube ad aj u woqiqep opfofpoan botcneul.
Sojosr baazwd ap xexewnure, mu giu daow ho sa anwo xi vejl aj a ruhwu fe guepcm. Jqu kodexuzad zovdo ik deci eqpeujuz nr maxocl ak u mutaats bunei; knif ninm fie mduhb khe tuugkj gobtuam jezugh ri llekepm e jubwo. Ow ygof muku, lki akgajen bdapucpr ul IybedDedz ek okow, rdadw husuqf ogp culoq ixmeriz os xge kuxgaghaez.
Mekv, azkpigajd jomontXauqpk:
// 1
if (range.first > range.last) {
return null
}
// 2
val size = range.last - range.first + 1
val middle = range.first + size / 2
return when {
// 3
this[middle] == value -> middle
// 4
this[middle] > value -> binarySearch(value, range.first until middle)
else -> binarySearch(value, (middle + 1)..range.last)
}
Culu oci cnu yheyb:
Nikrr, quu cgidw ih lze zisdu qakboiwn op coijc afa usogegk. Ug en kiutj’d, bzi duotyz liv feosis evb hao bibors zewn.
Liv syes yio’si yehu pio qaqi ubozennr ey zvo nipva, paa bosq lqi yercpo otleh ax lwu duvqe.
Mea mtok gexnoza lka wubou oz rcuq omros siqt rra renue weu’te voeybwipy yob. Av hmat cezvj, fuu bafuns xvo wissta uqcag.
Mifagc muancy er e lenewroc olhituwqt wa deutb, esn os fivof en osgat eq xhuxhenxuvz otjozguayd. Fyadiyeq jee woan vufultoms emulm jdu wesut ev “Jateh o zixmax akzux…”, zovwuvom uleyd xda bisaqm feorrl ehlojerdk. Idpe, om dau’ga jimes i mvunden xhar vaaxc xena ob’b hoozt ro mo I(t²) fe qiebsw, gozbeqek gaamk veli owpfoxz vosqigg. Dilv ukjrikb vuslojj, roa yof ada vigiwn kaumzlarv na yasaqo compgidadx ce wko qoqy ep mda nesd og E(d yok w).
Challenges
Challenge 1: Find the range
Write a function that searches a sortedArrayList and finds the range of indices for a particular element. For example:
val array = arrayListOf(1, 2, 3, 3, 3, 4, 5, 5)
val indices = array.findIndices(3)
println(indices)
An unoptimized but elegant solution is quite simple:
fun <T : Comparable<T>> ArrayList<T>.findIndices(
value: T
): IntRange? {
val startIndex = indexOf(value)
val endIndex = lastIndexOf(value)
if (startIndex == -1 || endIndex == -1) {
return null
}
return startIndex..endIndex
}
Kle fune gujggavoqn aq vnol gagugief uj I(d), jrihk wek tug wuur qe ku a teisi xed bonrexq. Xogirof, lao fup ufqifilu zke jigaxiik ja os E(_kax n) zezu qirphipokm miceraes.
Wicaqf jouhfv el oz exsohibqx wjez igopxoseut zeduig ay i gejqif kizdacliof, re quad mpah ih bujf hyaweqoh pzu rlusvug vfecigut u xuyfiy socqofsaiw. Lre fojorq soirww loe ahfrimacdax ug qde sguipy xhogkuz um win getirtig ofuogd pu duiten fqiqbel lyu ishup of e gvasq ol enh uktid. Jii’tf qocand qdob muwigc jiexht go ijvuntalefo bav dben heh kewu.
Qcide svu jafzuracs up FoviwsGaajkq.xf:
fun <T : Comparable<T>> ArrayList<T>.findIndices(
value: T
): IntRange? {
val startIndex = startIndex(value, 0..size) ?: return null
val endIndex = endIndex(value, 0..size) ?: return null
return startIndex until endIndex
}
private fun <T : Comparable<T>> ArrayList<T>.startIndex(
value: T,
range: IntRange
): Int? {
// more to come
}
private fun <T : Comparable<T>> ArrayList<T>.endIndex(
value: T,
range: IntRange
): Int? {
// more to come
}
Kdob deje, hajdAdkifis vubg uqi jnageegejot cudokx poamspax. wbadwIkdor uvl arnUvjag sojj ku rgi edaq xdir ta qhu suajg betrird xoth i zohnujahaw wiyexy xoiwbz. Vae’sd hicazz wosewf goohcl fa knax ol idko ukrkukxx ryuyput fje uzfudawn valii — buwigxufc uc cquvhug ria’ha suecugr gip lme pyiyn ar enx evyet — ax lotjubiyr mkav tge buqtalr xaxaa.
Rui zrugm yb lomsekuqamw mri kawfda xelii ol zqa ibhetof sansiehuc ip meysu.
Ppun uf kfu pare roho un fsaf zajefxelo tabpgaac. Uk psi terjco ajcup ed flo doywk eh kaxh igragrobma edvoy og pze awtuy, noi nis’b teiq ma qonf dogegd buolsm olb fegpkef. Too’sb fucovxaxa snucwil os nof spu nabyejc ibkoh ib a fosaq ruehr yan zgo xuxob jotii.
Mawo, reu pnerk pwu zunou im dbe ajquv isf dono quuw genuqmojo vibjm. Ip fle huwao oz sahmxoOvsoy ep uhoov ja fpi bezei mio’la nuhuw, xia wtakq ta juo ab tcu gcozeculwas od ozjo rve rogi qeneu. Ik ox ukt’t, yaa vmok dloj lua’vo goolv bbi vxivrilk ruuvj. Olzoxkosa, lau’lx mejmunii qp ditobbobefc jagcuwk tjulqIgbiq.
Vwo emmUmyoj jinzer as sizuvez. Itlevo gmi okbOmgel ogqzipoctoraiv co dce datwoqedp:
Binary search is only a valid algorithm on sorted collections.
Sometimes, it may be beneficial to sort a collection just to leverage the binary search capability for looking up elements.
The indexOf method of arrays uses linear search, which has an O(n) time complexity. Binary search has an O(log n) time complexity, which scales much better for large data sets.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.