Problem¶
Find a element x in a sorted array arr
For easier to follow:
1. We assuming arrayarris value is sorted from the lowest to highest.
2. The array is zero-index (arrstart from 0)
arr = [1,2, 2, 2, 2, 3, 4, 6, 8, 9, 142, 142, 142, 142, 255, 255, 255, 567, 1275, 1275, 1275, 2547, 2547, 5458, 9722, 92124]
x = 567
Solve¶
What happening?¶
We leverage on the characteristic of a sorted array, where a index i element always have bigger or equal value than element with smaller index than i.
and revert
This mean, if we access a value <any> of the arr, we know that the finding value x is either in the left, or in the right of the <any> element.
Pseudo code¶
While there is many way to choose the value <any> in arr, we specifically choose the middle of arr. By splitting at the middle, we can eliminate the most of arr in one comparing session.
- Start with the full array
arr, find the middle of the arrayarr, we calling itmidpoint, with valuearr[mid] - Base on the comparing result of
xandarr[mid], We narrowing down arrayarrfor searching:- If
x == arr[mid], returnTrueas we foundx - If
x < arr[mid],arrcan be narrowing down toarr[0..mid-1], as all value ofarr[mid .. n]is greater thanx - If
x > arr[mid],arrcan be narrowing down toarr[mid+1..len(arr) - 1], as all value ofarr[0 .. mid]is less thanx
- If
- Repeat the process with our new narrowed array
arr
This result on a O(log n) time complexity
Actual Implement¶
Personal preference¶
O(log n)
There is something call Off by one error causing a lot of debug time, so my general take on binary search is always:
(left, right) = (lowest, highest) = (-1, len(arr))(both left and high is not inclusive in the array from the beginning)
Why? There is several advantage problem related to binary search, that we will stump on:
- Find the first appearance of
xin array - Find the last appearance of
xin array - Find the all appearance of
xin array - Find the position to insert
xinto array so that arrayarrstill sorted
By using both left and right not in the array give me better control on how I want to lane left and right pointer in to array. This is a example on Find the all appearance of x in array arr:
isFoundtell us ifxinarror not- Where
lastPositiontell you the element with the biggest position inarrthat havexvalue
from math import trunc, log
def binarySearch(arr, x):
l, r = -1, len(arr)
n = len(arr)
logn = trunc(log(n+2,2))+1
for _ in range(logn):
m = (l + r) // 2
if l == r-1:
break
if x < arr[m]:
r = m
else:
l = m
assert l == r-1
return x == arr[l], l
arr = [1, 2, 2, 2, 2, 3, 4, 6, 8, 9, 142, 142, 142, 142, 255, 255, 255, 567, 1275, 1275, 1275, 2547, 2547, 5458, 9722, 92124]
x = 567
isFound, lastPossition = binarySearch(arr, x)
print(isFound, lastPossition)
Example:¶
| Problem | Last update |
|---|---|
| 74. Search a 2D Matrix | 8:52 PM - October 02, 2023 |
| 84. Largest Rectangle in Histogram | 8:52 PM - October 02, 2023 |
| 81. Search in Rotated Sorted Array II | 8:52 PM - October 02, 2023 |
| 274. H-Index | 8:52 PM - October 02, 2023 |
Typescript implementation¶
O(log n)
Not thing fancy, just pain
- For divining, JavaScript force us to use
(float)division result, we have to useMath.floor()(do not useMath.trunc()) - The implement just focus on finding the value, so it return on found value immediately
export default function bs_list(haystack: number[], needle: number): boolean {
let l = -1;
let r = haystack.length;
let m = 0;
while (true) {
m = Math.floor((l + r) / 2);
if (haystack[m] == needle)
return true;
if (l == m)
break;
if (haystack[m] < needle) {
l = m;
} else {
r = m;
}
}
return false
}
Created : August 28, 2023