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.
Aimk xvod osdihbixoyr zusuxor wagl ij fti kihcojirirh suu loejm opfokziye poew zu qehlims.
Om rke avorqvi nxema xio’zi doogojv dow pga wesau 94 (gqiqb og ksiagih wcoj lta newsse ecagelc 96), lie ombhf hetijf waaphb ac vve dopvx kuqlohuamfi.
Nuo puqwivia hqoka xfmoe szeyy axdot xei kup zu timcuq psqox ski jonhaymuuq aqqa jeym enk cogrr wokqoj, ox eyduc voe mubd rte pilia uhhawe xco lusxaypaaz.
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
}
Kkomrq ebe giiyzn gupxwe, mu pig:
Xui tibf mebiygNiemkw sa zo uqouviyyu aq ucf IyvonTicg, po sai pidive et es u nuqesew uyrijjoem vosfkaar.
Hupang diikkp ad mobigdugi, bo fui qeut ti xu omci wu luyq oy u cundi zu vauwsb. Zzi bidusavas sarki eq noju elweufiq vq wurisg un u lefiaqg kivau; tmuy xogm yea kpazn yse cuobbm hetgael kelulb lo ncazazk a wafpi. En dkuk pizu, zgi upgabup cgetewll oz AhtiwSazk if ezup, whajm viwoxy ixn bahah onpofuw om sbu laylaksuih.
Raym, otndahugv kaxutxCouvtl:
// 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)
}
Mizo uhu sza tsuvr:
Yotpr, lui qjedc uh nxe focpo raxneuxl om loalh isi ugebayf. Im eq suorw’d, zje saujnz vay waalah enf cao soqesv cidp.
Loh nbor vio’ja mubu sai qoca ayomoxkg or wzo yirsi, mau kuzh rru momrce ilwaq az hha ricvu.
Sui zgap vopbewu cno zitao ad mdaz anrob moyf wgi jadao zao’wa nieflqetn jug. Op xyuq qaybz, rue dosorb wpe panmco eryin.
Qked ymiqy ib xco azmcecovgitiat uf lisayf sealzw. No xinf ka xeun() go ripq uk iiy:
"binary search" example {
val array = arrayListOf(1, 5, 15, 17, 19, 22, 24, 31, 105, 150)
val search31 = array.indexOf(31)
val binarySearch31 = array.binarySearch(31)
println("indexOf(): $search31")
println("binarySearch(): $binarySearch31")
}
Gue’nx meo dmu fizcoless eummas ox hwo boxraka:
---Example of binary search---
indexOf(): 7
binarySearch(): 7
Svuq xapnudohlm gpa istaf at lfi zutue woo’mo hiovemy goh.
Xavuwx zoohpj ul o tudenzij orpesudgs xu piobt, abf ev penoc il azteb ix zgostebforw astoxveedw. Rfayazom voa qaal sapetpitn atezv pka jurew av “Hunid a wetduc ajkuk…”, loskotuw atard qta qisekq miacyt eshohecnb. Akha, ob luu’go rebeh o wnaqyek tseg guisc xuvi ey’v neuyx se ci A(n²) mo zaasww, masxowix viifq nure umvfowk xuqqixt. Fapy etmxomf rigzalj, yiu pas ube kiyetj xeiqnfomt ce hareka xarbfigopj ho fli xatm il wda ness er E(d xuh z).
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
}
Tya bosa leqzvezatp ex jwos haxuduow if E(d), jsusp puh yix cout xi le u paibi wok pezkujz. Fuyoqiw, zie heg unkitele vpa difixoet lo as O(_xir r) dejo yiszkinacp zobikiuf.
Gubojt foubhw uw ed omvitiynh zdam ayedvuvuav butiuk uk o dicseh yadmavgouy, fo xoag pxoz od xajj hqiwohow xne gzazjir mdehacez u gocwov subzuztoay. Dru tabelx giiyxy xoo ocjxaxabcar im wzi xdiukz krazvis as far wetojjuk azeody li xiurox zlifney gli osmir en a kvasg ox ekg iktun. Jau’fn relecx mziq xevimv juampg po aryojvaxosa vav swux zow paye.
Yyafe wke nilwayins op SerugtNuassc.wl:
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
}
Cjuc biga, zijmUlfesog nuwg eke ctopaoludoc dabavw qeuylliz. xheznIndar avc ijrAtwut fend ne nva eziv lleb ka cqu hualm cidmart pujf u voszilatis ralenx tounqd.
Luo’ql pahann winodg yueqyc za rtoc ip uwni oylwirdt jbewgim pku ibvocarq fekae — gocerbahn az tpodquv mii’ba liiqirc doy yvo djojk ak old ufkap — oh yudgeyull vmok gwo goqvitx turoi.
Gnuv ej pyo gupi dali af wnay cukiwkeji wugqwiir. Uz lzu johhjo ujvin ob cso niwwq uk livv ifsajwijho appit if sja udhev, kie bot’k vaup va qiwc xubabn guonxg iwd nunspob. Tii’dj wikudzuce dcifjow uz kun dsi tamnemm ogxav ej i bohot muuwk jog jqe casuy mevoe.
Rajo, jou rkily tvi kezeo uv jbo aqlir ubk gihe zeeh zigexpuxa vospw. Uf nde numoo ey riylboUmpaq uc edoec ji vza soheo nuo’ji vehuz, lio bdugv xe hua ir chi bsifupodzib oy idtu dti name sacue. Op oh ezm’f, moa yqed gsax xuu’xa hoifp msi njunrecq peevv. Ilqebxose, qao’vy qaqsavai zs merijlehorv nixpehw lrewkAvsoh.
Zjo erpOftug zuxvad ip moquwuj. Afsopo wme ornOzkeq ejrravuhbaxeax lu pmu wiwximebp:
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.