Introduction
Sorting organises data — searching finds data. These two skills go hand in hand: many of the best search techniques only work when the data is already sorted.
In this post, we cover the two essential search algorithms:
- Linear Search — check every element, one by one. Simple but slow.
- Binary Search — repeatedly halve the search space. Fast but requires sorted data.
Linear Search
How It Works
Imagine you dropped your keys somewhere in your house. You start at the front door and check every room, one by one, until you find them (or run out of rooms).
That is Linear Search: start at the beginning, look at each element, and stop when you find what you are looking for.
Step-by-Step Walkthrough
Find 27 in the array [14, 33, 27, 10, 45, 8].
| Index | Element | Match? |
|---|---|---|
| 0 | 14 | ❌ |
| 1 | 33 | ❌ |
| 2 | 27 | ✅ Found at index 2! |
We checked 3 elements before finding the target.
Java Implementation
public class LinearSearch {
/**
* Searches for a target value in an unsorted array.
* Returns the index if found, -1 otherwise.
*/
public static int linearSearch(int[] arr, int target) {
for (int i = 0; i < arr.length; i++) {
if (arr[i] == target) {
return i; // found — return the index
}
}
return -1; // not found
}
public static void main(String[] args) {
int[] data = {14, 33, 27, 10, 45, 8};
int result = linearSearch(data, 27);
System.out.println(result); // Output: 2
}
}
Complexity
| Case | Time | Explanation |
|---|---|---|
| Best | $O(1)$ | Target is the first element. |
| Average | $O(n)$ | Target is somewhere in the middle. |
| Worst | $O(n)$ | Target is the last element or not present. |
| Space | $O(1)$ | |:—:|:—:|
Binary Search
How It Works
Now imagine your keys are hidden in one of 1,000 numbered lockers, and you know the lockers are sorted by some clue. Instead of opening every locker, you:
- Go to the middle locker (#500).
- A sign tells you whether your keys are in a locker with a higher or lower number.
- You eliminate half the lockers and repeat.
After just 10 steps ($\log_2 1000 ≈ 10$), you have found your keys. That is the power of $O(\log n)$.
Requirements
Binary Search only works on sorted data. If the array is unsorted, you must sort it first (see our sorting posts).
Step-by-Step Walkthrough
Find 23 in the sorted array [5, 8, 12, 17, 23, 38, 42, 56, 71].
| Step | low | high | mid | arr[mid] | Comparison | Action |
|---|---|---|---|---|---|---|
| 1 | 0 | 8 | 4 | 23 | 23 == 23 | ✅ Found at index 4! |
That was lucky — let’s try a harder one. Find 38.
| Step | low | high | mid | arr[mid] | Comparison | Action |
|---|---|---|---|---|---|---|
| 1 | 0 | 8 | 4 | 23 | 38 > 23 | Search right half: low = 5 |
| 2 | 5 | 8 | 6 | 42 | 38 < 42 | Search left half: high = 5 |
| 3 | 5 | 5 | 5 | 38 | 38 == 38 | ✅ Found at index 5! |
Only 3 steps to search a 9-element array. For a million elements, it would take at most 20 steps.
Now let’s find 15 (which is NOT in the array).
| Step | low | high | mid | arr[mid] | Comparison | Action |
|---|---|---|---|---|---|---|
| 1 | 0 | 8 | 4 | 23 | 15 < 23 | Search left half: high = 3 |
| 2 | 0 | 3 | 1 | 8 | 15 > 8 | Search right half: low = 2 |
| 3 | 2 | 3 | 2 | 12 | 15 > 12 | Search right half: low = 3 |
| 4 | 3 | 3 | 3 | 17 | 15 < 17 | Search left half: high = 2 |
| 5 | 3 | 2 | — | — | low > high | ❌ Not found! |
Java Implementation
Iterative Version
public class BinarySearch {
/**
* Searches for a target in a SORTED array using Binary Search (iterative).
* Returns the index if found, -1 otherwise.
*/
public static int binarySearch(int[] sortedArr, int target) {
int low = 0;
int high = sortedArr.length - 1;
while (low <= high) {
// Calculate mid safely to avoid integer overflow
int mid = low + (high - low) / 2;
if (sortedArr[mid] == target) {
return mid; // target found
} else if (sortedArr[mid] < target) {
low = mid + 1; // target is in the right half
} else {
high = mid - 1; // target is in the left half
}
}
return -1; // target not found
}
public static void main(String[] args) {
int[] sorted = {5, 8, 12, 17, 23, 38, 42, 56, 71};
System.out.println(binarySearch(sorted, 38)); // Output: 5
System.out.println(binarySearch(sorted, 15)); // Output: -1
}
}
Recursive Version
public static int binarySearchRecursive(int[] arr, int target, int low, int high) {
// Base case: search space is exhausted
if (low > high) return -1;
int mid = low + (high - low) / 2;
if (arr[mid] == target) {
return mid;
} else if (arr[mid] < target) {
return binarySearchRecursive(arr, target, mid + 1, high); // right half
} else {
return binarySearchRecursive(arr, target, low, mid - 1); // left half
}
}
Key Lines Explained
| Line | Purpose |
|---|---|
int mid = low + (high - low) / 2; | Calculate middle index. We avoid (low + high) / 2 because that can overflow for very large values of low and high. |
while (low <= high) | We continue searching as long as there is at least one element in the search range. When low > high, the range is empty. |
low = mid + 1; or high = mid - 1; | We exclude mid from the next search because we already checked it. This ensures the search space shrinks every iteration. |
Complexity
| Case | Time | Explanation |
|---|---|---|
| Best | $O(1)$ | Target is exactly the middle element on the first try. |
| Average | $O(\log n)$ | Each step halves the search space. |
| Worst | $O(\log n)$ | Target is at the extreme or not present. |
| Space (iterative) | $O(1)$ |
|---|---|
| Space (recursive) | $O(\log n)$ — recursion stack |
Linear vs Binary Search
| Feature | Linear Search | Binary Search |
|---|---|---|
| Requires sorted data? | ❌ No | ✅ Yes |
| Best-case time | $O(1)$ | $O(1)$ |
| Worst-case time | $O(n)$ | $O(\log n)$ ✅ |
| Space | $O(1)$ | $O(1)$ iterative |
| Implementation | Trivial | Slightly more complex |
| Best for | Small or unsorted data | Large sorted datasets |
When to Use / When NOT to Use
| ✅ Use Linear Search When | ✅ Use Binary Search When |
|---|---|
| Data is unsorted and you need a one-off lookup | Data is sorted (or you can sort it once and search many times) |
| Dataset is very small (< 20 elements) | Dataset is large (thousands to millions of elements) |
| You’re searching a linked list (no random access) | You have random access (arrays, not linked lists) |
Practice Problems
- Binary Search – LeetCode #704 — Classic implementation practice.
- Search Insert Position – LeetCode #35 — Find where a target would be inserted in a sorted array.
- First Bad Version – LeetCode #278 — A creative Binary Search application.
- Find Minimum in Rotated Sorted Array – LeetCode #153 — Binary Search on a twist.
What’s Next?
Binary Search showed us the power of reducing the search space. Next, we explore a related technique that uses two pointers to solve problems on sorted arrays and linked lists efficiently: Two Pointer Technique.