Linear Search Algorithm Explained — How It Works, When to Use It, and Why It Matters
- Linear search checks every element one by one from start to finish — it needs no sorting, no preprocessing, and no special data structure. That simplicity is a feature, not just a limitation.
- Worst-case time complexity is O(n) — if the target is last or absent, you check every element. Best case is O(1). Space complexity is always O(1) because no extra memory is allocated regardless of input size.
- Always use .equals() to compare Strings and always return -1 (not 0) for 'not found' — these two conventions prevent the two most common linear search bugs beginners write in Java.
Imagine you've got a messy drawer full of socks and you're looking for the one red sock. You don't magically know where it is, so you pick up the first sock, check if it's red, put it down if it's not, then pick up the next one — and so on until you find it. That's linear search. You check every single item, one at a time, in order, until you find what you're looking for (or run out of socks). No tricks, no shortcuts — just a straightforward, honest search from start to finish.
Every app you've ever used searches for something. Your music app searches for a song by name. Your contacts app finds a phone number. Your email client hunts for a message from last Tuesday. Under the hood, all of these rely on some form of search algorithm — a set of steps a computer follows to find a specific piece of data inside a collection. Without search algorithms, every piece of software that handles data would be helpless. Linear search is the most fundamental of them all, and understanding it is the foundation for understanding everything smarter that comes after it.
The problem linear search solves is deceptively simple: given a list of items, find whether a specific target item exists in that list, and if so, tell us exactly where it is. Sounds easy, right? But computers don't have eyes. They can't 'glance' at a list and spot something instantly. They need explicit instructions: start here, check this, move to the next one. Linear search gives them those exact instructions in the most straightforward way possible — check every element, one at a time, from the beginning to the end.
By the end of this article, you'll understand exactly how linear search works step by step, you'll be able to write a complete, working linear search function in Java from memory, you'll know its time and space complexity and what that means in plain English, and you'll know precisely when to reach for it — and when to put it down and use something better. You'll also walk away with the two gotchas that trip up almost every beginner, and the interview answers that will make you sound like you actually understand what's happening under the hood.
How Linear Search Works — Step by Step
Linear search scans each element sequentially from left to right until the target is found or the array is exhausted.
- Start at index i=0.
- Compare arr[i] with the target.
- If arr[i] == target: return i (target found at this index).
- If i == len(arr)-1 and no match: return -1 (target not in array).
- Otherwise: increment i and repeat from step 2.
For arr=[5,2,8,1,9] and target=8: - i=0: arr[0]=5 ≠ 8. i=1: arr[1]=2 ≠ 8. i=2: arr[2]=8 == 8. Return 2.
For target=7: i=0,1,2,3,4 — none match. Return -1.
Best case: O(1) when target is the first element. Worst case: O(n) when target is last or absent. Average case: O(n/2) = O(n). No preprocessing required, works on unsorted data, suitable for any sequence.
Worked Example — Sentinel Linear Search
Sentinel search is an optimization that eliminates the bounds check. Place the target at the end of the array as a sentinel, guaranteeing the loop always terminates at the target:
arr=[5,2,8,1,9], target=3. Append 3 as sentinel → [5,2,8,1,9,3]. i=0: 5≠3. i=1: 2≠3. i=2: 8≠3. i=3: 1≠3. i=4: 9≠3. i=5: 3==3 (sentinel). Check if i < original length (5): 5 is not < 5 → target not found.
The sentinel eliminates the 'i < len(arr)' bounds check from each iteration, reducing the number of comparisons per iteration from 2 to 1. For n=1000 elements, this halves the comparison count. The benefit is most noticeable in tight loops with simple element types.
How Linear Search Actually Works — Step by Step
Let's make this concrete. Say you have an array of five student ID numbers: [1042, 3387, 2291, 4410, 1895]. You want to find whether ID number 4410 exists in that list.
Linear search does this: it starts at index 0 (the first position) and asks 'is this 4410?' The answer is no — it's 1042. So it moves to index 1 and asks the same question. No, that's 3387. Index 2? No, 2291. Index 3? Yes — 4410 matches! The algorithm stops and reports back: 'Found it at position 3.'
If the target wasn't in the list at all, the algorithm would keep going until it ran out of elements, then report 'not found.' That's it. No magic. No sorting required. No preprocessing. Just a simple, honest loop.
One thing that trips people up early: the algorithm stops as soon as it finds the first match. If your list has duplicates, linear search returns the index of the very first occurrence and doesn't keep looking. This is almost always the right behaviour, but it's worth knowing.
public class LinearSearchBasic { /** * Searches for a target value inside an array of integers. * * @param numbers The array we want to search through * @param target The number we're looking for * @return The index where the target was found, or -1 if it doesn't exist */ public static int linearSearch(int[] numbers, int target) { // Start at the very first element (index 0) and walk forward one step at a time for (int index = 0; index < numbers.length; index++) { // Ask the key question: is THIS element the one we're looking for? if (numbers[index] == target) { // Yes! Stop immediately and report WHERE we found it return index; } // No match — the loop automatically moves to the next index } // If we reach here, we checked every single element and found nothing // Returning -1 is the universal convention for 'not found' return -1; } public static void main(String[] args) { int[] studentIds = {1042, 3387, 2291, 4410, 1895}; int targetId = 4410; int resultIndex = linearSearch(studentIds, targetId); // -1 means the target was not found anywhere in the array if (resultIndex != -1) { System.out.println("Student ID " + targetId + " found at index " + resultIndex); } else { System.out.println("Student ID " + targetId + " does not exist in the list."); } // Now test the 'not found' case int missingId = 9999; int missingResult = linearSearch(studentIds, missingId); if (missingResult != -1) { System.out.println("Student ID " + missingId + " found at index " + missingResult); } else { System.out.println("Student ID " + missingId + " does not exist in the list."); } } }
Student ID 9999 does not exist in the list.
String.indexOf(), Python's list.find(), etc.). You can't use 0 because 0 is a valid index — it means 'found at the very first position.' Negative numbers can never be valid array indices, so -1 is a safe, unambiguous sentinel value.Time and Space Complexity — What It Costs to Run Linear Search
Every algorithm has a cost. That cost is measured in two ways: time (how many steps does it take?) and space (how much extra memory does it need?). Understanding this for linear search is crucial — not because it's hard, but because it's the baseline you'll compare every other search algorithm against for the rest of your career.
Time Complexity — the 'how long' question: In the best case, the target is the very first element. One comparison, done. That's O(1) — constant time. In the worst case, the target is the last element, or it's not in the list at all. You checked every single element — that's n comparisons for a list of n items. That's O(n) — linear time, which is where the algorithm gets its name. On average, you'll find the target somewhere in the middle, which is roughly n/2 comparisons — still O(n) because we drop constants in Big O notation.
Space Complexity — the 'how much memory' question: Linear search is O(1) space. It doesn't create any new arrays or data structures. It just uses a single loop variable (the index counter). No matter if your input has 10 items or 10 million, the extra memory used stays constant.
The honest takeaway: linear search is slow for large datasets but costs almost nothing in memory. It's the algorithm equivalent of a reliable old bicycle — not the fastest thing on the road, but it always gets you there and never breaks down.
public class LinearSearchComplexityDemo { // We'll count comparisons manually so you can SEE the O(n) behaviour public static int linearSearchWithCount(int[] numbers, int target) { int comparisonCount = 0; // Track how many times we check an element for (int index = 0; index < numbers.length; index++) { comparisonCount++; // Every loop iteration is one comparison if (numbers[index] == target) { System.out.println("Found after " + comparisonCount + " comparison(s)."); return index; } } System.out.println("Not found. Made " + comparisonCount + " comparison(s) — checked every element."); return -1; } public static void main(String[] args) { int[] temperatures = {72, 68, 91, 55, 83, 77, 64, 98, 45, 88}; // Array has 10 elements (indices 0 through 9) System.out.println("--- Best Case: Target is the FIRST element ---"); linearSearchWithCount(temperatures, 72); // At index 0 System.out.println(); System.out.println("--- Average Case: Target is somewhere in the MIDDLE ---"); linearSearchWithCount(temperatures, 83); // At index 4 System.out.println(); System.out.println("--- Worst Case: Target is the LAST element ---"); linearSearchWithCount(temperatures, 88); // At index 9 System.out.println(); System.out.println("--- Worst Case: Target does NOT exist ---"); linearSearchWithCount(temperatures, 100); // Not in the array } }
Found after 1 comparison(s).
--- Average Case: Target is somewhere in the MIDDLE ---
Found after 5 comparison(s).
--- Worst Case: Target is the LAST element ---
Found after 10 comparison(s).
--- Worst Case: Target does NOT exist ---
Not found. Made 10 comparison(s) — checked every element.
Linear Search on Strings and Custom Objects — It's Not Just for Numbers
Every example you see in textbooks uses integers. That's fine for learning, but real-world code searches through names, emails, product titles, and custom objects. Linear search works on all of these — the logic is identical. The only thing that changes is how you compare two elements.
With integers, you use ==. With Strings in Java, you must use .equals() — because == on objects checks whether two variables point to the same memory address, not whether they have the same content. This is one of the most common bugs beginners write, and it's the kind of bug that can pass your own manual tests but fail in production when the string comes from user input or a database.
With custom objects (like a Student class), you decide what 'equal' means. You might search by name, by ID, or by email. You write the comparison logic yourself. This makes linear search incredibly flexible — you can search any collection for any criteria without sorting or pre-processing anything first. That flexibility is genuinely valuable in small collections and quick scripts.
public class LinearSearchStringsAndObjects { // --- Searching through an array of Strings --- public static int searchByName(String[] names, String targetName) { for (int index = 0; index < names.length; index++) { // CRITICAL: Use .equals() for Strings, NOT == // .equals() compares the actual text content character by character if (names[index].equals(targetName)) { return index; } } return -1; // Name not found } // --- A simple Student record to demonstrate searching objects --- static class Student { int studentId; String fullName; double gpa; Student(int studentId, String fullName, double gpa) { this.studentId = studentId; this.fullName = fullName; this.gpa = gpa; } } // --- Searching through an array of Student objects by their ID --- public static Student searchById(Student[] roster, int targetId) { for (int index = 0; index < roster.length; index++) { // We define what 'match' means: two students match if their IDs are equal if (roster[index].studentId == targetId) { return roster[index]; // Return the whole Student object, not just the index } } return null; // Convention: return null when a searched object isn't found } public static void main(String[] args) { // --- String search demo --- String[] cityNames = {"Austin", "Denver", "Phoenix", "Nashville", "Portland"}; String searchCity = "Nashville"; int cityIndex = searchByName(cityNames, searchCity); if (cityIndex != -1) { System.out.println(searchCity + " found at index " + cityIndex); } else { System.out.println(searchCity + " is not in the list."); } // --- Object search demo --- Student[] classRoster = { new Student(1001, "Maria Chen", 3.8), new Student(1042, "James Okafor", 3.5), new Student(1087, "Priya Nair", 3.9), new Student(1103, "Lucas Ferreira", 3.2) }; int searchId = 1087; Student foundStudent = searchById(classRoster, searchId); if (foundStudent != null) { System.out.println("Found student: " + foundStudent.fullName + " | GPA: " + foundStudent.gpa); } else { System.out.println("No student with ID " + searchId + " found."); } } }
Found student: Priya Nair | GPA: 3.9
When to Use Linear Search — and When to Walk Away
Linear search isn't a bad algorithm. It's a misused one. Knowing when it's exactly the right tool is what separates a developer who memorised a concept from one who actually understands it.
Use linear search when: Your list is small (under a few hundred items) and performance isn't critical. Your data is unsorted and you can't afford the time to sort it first. You're searching based on a condition that can't be indexed, like 'find the first student with a GPA above 3.7' — you genuinely have to check each one. You're writing a quick script or throwaway tool and simplicity beats optimisation.
Don't use linear search when: Your dataset is large (thousands of records or more) and you're searching repeatedly. In that case, binary search (for sorted data) gives you O(log n) — searching a million items in about 20 steps instead of a million. Or use a HashMap for O(1) lookup by key. The performance difference becomes dramatic at scale.
The honest real-world truth: most production code that 'searches a list' is actually using a database index, a HashMap, or a sorted structure. But every single one of those was built by someone who first understood linear search. It's the bedrock.
import java.util.ArrayList; import java.util.List; public class LinearSearchRealWorldUse { // Real-world use case: find all products under a given price threshold // This CAN'T use binary search because we want ALL matches, not just one, // and the condition is a range, not an exact value. // Linear search is genuinely the right tool here. static class Product { String name; double priceInDollars; boolean inStock; Product(String name, double priceInDollars, boolean inStock) { this.name = name; this.priceInDollars = priceInDollars; this.inStock = inStock; } } // Returns ALL in-stock products at or below the budget — not just the first one public static List<Product> findAffordableInStockProducts( Product[] catalogue, double budget) { List<Product> matches = new ArrayList<>(); for (int index = 0; index < catalogue.length; index++) { // Two conditions must BOTH be true to add this product to results boolean withinBudget = catalogue[index].priceInDollars <= budget; boolean available = catalogue[index].inStock; if (withinBudget && available) { matches.add(catalogue[index]); // Collect the match; keep going } // Notice: we do NOT return early — we need to check every product } return matches; // Return everything we found } public static void main(String[] args) { Product[] storeCatalogue = { new Product("Wireless Earbuds", 79.99, true), new Product("Laptop Stand", 45.00, true), new Product("Mechanical Keyboard", 129.99, false), // Out of stock new Product("USB Hub", 35.50, true), new Product("Webcam HD", 89.99, true), new Product("Monitor Light", 49.99, false) // Out of stock }; double userBudget = 80.00; List<Product> recommendations = findAffordableInStockProducts(storeCatalogue, userBudget); System.out.println("In-stock products under $" + userBudget + ":"); for (Product product : recommendations) { System.out.println(" - " + product.name + " ($" + product.priceInDollars + ")"); } } }
- Wireless Earbuds ($79.99)
- Laptop Stand ($45.0)
- USB Hub ($35.5)
| Feature / Aspect | Linear Search | Binary Search |
|---|---|---|
| Requires sorted data? | No — works on any array | Yes — data MUST be sorted first |
| Time complexity (worst) | O(n) — checks every element | O(log n) — halves the search space each step |
| Time complexity (best) | O(1) — target is first element | O(1) — target is middle element |
| Space complexity | O(1) — no extra memory needed | O(1) iterative / O(log n) recursive |
| Works on unsorted data? | Yes, always | No — gives wrong results on unsorted data |
| Works on linked lists? | Yes — just traverse forward | No — requires random index access |
| Implementation complexity | Very simple — a single loop | Moderate — tricky boundary conditions |
| Best used when | Small data, unsorted, complex conditions | Large sorted data, repeated exact lookups |
| Can find ALL matches? | Yes — just don't return early | Not easily — finds one match near the middle |
🎯 Key Takeaways
- Linear search checks every element one by one from start to finish — it needs no sorting, no preprocessing, and no special data structure. That simplicity is a feature, not just a limitation.
- Worst-case time complexity is O(n) — if the target is last or absent, you check every element. Best case is O(1). Space complexity is always O(1) because no extra memory is allocated regardless of input size.
- Always use .equals() to compare Strings and always return -1 (not 0) for 'not found' — these two conventions prevent the two most common linear search bugs beginners write in Java.
- Linear search is the right choice for small or unsorted data and for complex multi-condition searches. For large sorted datasets with repeated lookups, binary search (O(log n)) or a HashMap (O(1)) will dramatically outperform it.
⚠ Common Mistakes to Avoid
Interview Questions on This Topic
- QWhat is the time complexity of linear search in the best, average, and worst case — and can you explain what causes each case to occur?
- QIf I have a sorted array of 10,000 integers and I need to search it thousands of times per second, would you use linear search? What would you use instead and why?
- QHow would you modify a linear search function to return ALL indices where a target value appears, rather than just the first one? What change does this force you to make to the function's return type and early-exit logic?
Frequently Asked Questions
What is linear search and when should I use it?
Linear search is an algorithm that finds a target value in a list by checking each element one at a time from the beginning until it finds a match or runs out of elements. Use it when your data is unsorted, your list is small, or your search condition is too complex for indexed lookups — like finding all records that satisfy multiple field conditions simultaneously.
What is the time complexity of linear search?
Linear search has O(1) best-case time complexity (when the target is the very first element), O(n) worst-case complexity (when the target is last or doesn't exist), and O(n) average-case complexity. Its space complexity is always O(1) because it uses only a loop counter and no additional data structures.
Does linear search require the array to be sorted?
No — and that's one of its biggest advantages over binary search. Linear search works correctly on completely unsorted data because it doesn't make any assumptions about the order of elements. It simply checks each one in sequence. Binary search, by contrast, will give wrong results on unsorted data because its halving logic depends on the sorted order being intact.
When should I use linear search over binary search?
Use linear search when: the array is unsorted (binary search requires sorted input), the array is very small (binary search overhead not worth it for n<10), you are searching a linked list (no random access for binary search), or you need the first occurrence and cannot sort the input. Binary search is O(log n) but requires O(n log n) preprocessing to sort.
Can linear search be parallelized?
Yes. Split the array into p chunks and search each chunk in parallel. The first thread to find the target signals the others to stop. On p processors, expected time reduces to O(n/p). This approach is used in GPU computing (parallel reduction) and MapReduce-style distributed search.
Developer and founder of TheCodeForge. I built this site because I was tired of tutorials that explain what to type without explaining why it works. Every article here is written to make concepts actually click.