Overview#
Exponential search is an efficient algorithm for searching in sorted arrays, especially when the array size is unknown or potentially infinite. It combines two main steps:
- Find the range where the target element may be present by exponentially increasing the search bounds.
- Perform binary search within the found range.
Steps#
- Start with a subarray size of
1
, compare its last element with the target x
.
- Double the subarray size (
2
, 4
, 8
, …) until the last element of the subarray is greater than or equal to x
.
- Once an index
i
is found such that arr[i] >= x
, the element must be present between i/2
and i
(because the previous doubling did not find a greater value).
- Perform binary search in the range
[i/2, i]
.
Code#
C++#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Solution {
public:
int exponentialSearch(const vector<int>& arr, int x) {
if (arr[0] == x) return 0;
int i = 1;
while (i < arr.size() && arr[i] <= x) i *= 2;
int left = i / 2, right = min(i, (int)arr.size() - 1);
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == x) return mid;
else if (arr[mid] < x) left = mid + 1;
else right = mid - 1;
}
return -1;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
func exponentialSearch(arr []int, x int) int {
if arr[0] == x {
return 0
}
i := 1
for i < len(arr) && arr[i] <= x {
i *= 2
}
left, right := i/2, min(i, len(arr)-1)
for left <= right {
mid := left + (right-left)/2
if arr[mid] == x {
return mid
} else if arr[mid] < x {
left = mid + 1
} else {
right = mid - 1
}
}
return -1
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
|
Java#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class Solution {
public int exponentialSearch(int[] arr, int x) {
if (arr[0] == x) return 0;
int i = 1;
while (i < arr.length && arr[i] <= x) i *= 2;
int left = i / 2, right = Math.min(i, arr.length - 1);
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == x) return mid;
else if (arr[mid] < x) left = mid + 1;
else right = mid - 1;
}
return -1;
}
}
|
Kotlin#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Solution {
fun exponentialSearch(arr: IntArray, x: Int): Int {
if (arr[0] == x) return 0
var i = 1
while (i < arr.size && arr[i] <= x) i *= 2
var left = i / 2
var right = minOf(i, arr.size - 1)
while (left <= right) {
val mid = left + (right - left) / 2
if (arr[mid] == x) return mid
else if (arr[mid] < x) left = mid + 1
else right = mid - 1
}
return -1
}
}
|
Python#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class Solution:
def exponential_search(self, arr: list[int], x: int) -> int:
if arr[0] == x:
return 0
i = 1
while i < len(arr) and arr[i] <= x:
i *= 2
left, right = i // 2, min(i, len(arr) - 1)
while left <= right:
mid = left + (right - left) // 2
if arr[mid] == x:
return mid
elif arr[mid] < x:
left = mid + 1
else:
right = mid - 1
return -1
|
Rust#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
impl Solution {
pub fn exponential_search(arr: &[i32], x: i32) -> i32 {
if arr[0] == x {
return 0;
}
let mut i = 1;
while i < arr.len() && arr[i] <= x {
i *= 2;
}
let (mut left, mut right) = (i / 2, std::cmp::min(i, arr.len() - 1));
while left <= right {
let mid = left + (right - left) / 2;
if arr[mid] == x {
return mid as i32;
} else if arr[mid] < x {
left = mid + 1;
} else {
right = mid - 1;
}
}
-1
}
}
|
TypeScript#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class Solution {
exponentialSearch(arr: number[], x: number): number {
if (arr[0] === x) return 0;
let i = 1;
while (i < arr.length && arr[i] <= x) i *= 2;
let left = Math.floor(i / 2), right = Math.min(i, arr.length - 1);
while (left <= right) {
const mid = left + Math.floor((right - left) / 2);
if (arr[mid] === x) return mid;
else if (arr[mid] < x) left = mid + 1;
else right = mid - 1;
}
return -1;
}
}
|
Complexity#
- ⏰ Time complexity:
O(log n)
— Exponential search finds the range in O(log n)
, then binary search finds the element in O(log n)
.
- 🧺 Space complexity:
O(1)
— With iterative binary search, only constant extra space is used.
Applications#
- Exponential search is particularly useful for unbounded searches, where the size of the array is infinite or unknown.
- It works better than binary search for bounded arrays, especially when the element to be searched is closer to the first element.