Searching Algorithms
A bunch of searching algorithms on arrays 🔎.
Linear Search
Rust
#![allow(unused)] fn main() { pub fn linear_search<T: Eq>(array: &[T], value: T) -> Option<usize> { array .iter() .enumerate() .find_map(|(i, v)| if *v == value { Some(i) } else { None }) } }
Java
public static <T> Optional<Integer> search(T[] array, T toFind) {
for (var index = 0; index < array.length; index++)
if (array[index] == toFind)
return Optional.of(index);
return Optional.empty();
}
Binary Search
In the course, you will study the recursive implementation of the binary search, in my code, I've written an iterative one (I don't "like" recurion)
Rust
#![allow(unused)] fn main() { pub fn binary_search<T: Ord>(array: &[T], value: T) -> Option<usize> { let mut step = array.len(); let mut index = 0; while step > 0 { let next = index + step; while next < array.len() { let cmp = match array.get(next) { Some(v) => v.cmp(&value), None => break, }; match cmp { Equal => return Some(next), Less => index = next, Greater => break, } } step /= 2; } None } }
Java
public static <T extends Comparable<? super T>> Optional<Integer> binarySearch(T[] array, T toFind) {
int jump = array.length - 1, index = 0;
while (jump > 0) {
while (index + jump < array.length) {
var comparison = array[index + jump].compareTo(toFind);
if (comparison > 0)
break;
index += jump;
if (comparison == 0)
return Optional.of(index);
}
jump /= 2;
}
return Optional.empty();
}
Exercise
Given , an
array of integers
, and two values and , with , count how many elements of are included in the range
The simplest way to solve the problem is to implement two functions: lower_bound
and upper_bound
, which are basically binary searches that don't stop once they find the value in the array. In the case of lower_bound
, it finds the index of "the smallest value bigger or equal to ", and the upper_bound
is "the biggest value smaller or equal to " with being the value to find.
This way, we can find the upper_bound
of , and the lower_bound
of , and do a subtraction of the two to find the number of elements inbetween. There are a few corner cases to consider both for upper_bound
, lower_bound
and count_in_range
(the function that solves the exercise) for which we return 0 (open an ISSUE if you want me to discuss them).
Rust
#![allow(unused)] fn main() { pub fn upper_bound<T: Ord>(array: &Vec<T>, value: T) -> Option<usize> { let mut step = array.len(); let mut index = 0; if array.first().unwrap() > &value { return None; } while step > 0 { let next = index + step; while next < array.len() { let cmp = match array.get(next) { Some(v) => v.cmp(&value), None => break, }; match cmp { Greater => break, _ => index = next, } } step /= 2; } Some(index) } }
#![allow(unused)] fn main() { pub fn lower_bound<T: Ord>(vector: &Vec<T>, value: T) -> Option<usize> { let mut step = vector.len(); let mut index = vector.len() - 1; if vector.last().unwrap() < &value { return None; } while step > 0 { while step <= index { let cmp = match vector.get(index - step) { Some(v) => v.cmp(&value), None => break, }; match cmp { Less => break, _ => index -= step, } } step /= 2; } Some(index) } }
#![allow(unused)] fn main() { pub fn count_in_range<T: Ord>(vector: Vec<T>, lower: T, upper: T) -> usize { let lower = lower_bound(&vector, lower); let upper = upper_bound(&vector, upper); if let (Some(l), Some(u)) = (lower, upper) { return match l.cmp(&u) { Greater => 0, _ => u.abs_diff(l) + 1, }; } 0 } }
Java
TODO: make bound functions return Optional, handle corner cases
public static <T extends Comparable<? super T>> Integer upperBound(List<T> list, T toFind) {
int jump = list.size() - 1, index = 0;
while (jump > 0) {
while (index + jump < list.size() && list.get(index + jump).compareTo(toFind) <= 0)
index += jump;
jump /= 2;
}
return index;
}
public static <T extends Comparable<? super T>> Integer lowerBound(List<T> list, T toFind) {
int jump = list.size() - 1, index = list.size() - 1;
while (jump > 0) {
while (index - jump >= 0 && list.get(index - jump).compareTo(toFind) >= 0)
index -= jump;
jump /= 2;
}
return index;
}
TODO: write a countInRange method