Skip to content
Ameen Abozaid
PublishedBEG-017-L02

Linear search

  • Lesson 2 of 7
  • 9 min read
  • Beginner
On This Lesson 11 topics

Lesson Overview

The last lesson introduced two ways to find "Mona" in a list: read from the top, or open in the middle. This lesson writes the first one in Java. Linear search checks each element in order, starting at index 0, until it finds the target or runs out of elements.

It is the simplest searching algorithm and it works on any array, sorted or not. It is also the baseline we will compare faster algorithms against, so we will practise counting its comparisons.

Why this matters: a surprising amount of real code is a linear search in disguise (look through the list for the matching id). Knowing exactly what it costs lets you decide when it is fine and when it is not.

This lesson builds on "What an algorithm is" and on arrays, for loops, and methods.

Learning Objectives

By the end of this lesson you will be able to:

  • Describe linear search in plain steps.
  • Implement linearSearch(int[] a, int target) that returns the index of the target, or -1 if it is absent.
  • Explain why -1 is a sensible "not found" value.
  • Trace a linear search with a variable table.
  • Count the comparisons for the best, worst, and a typical case.
  • Adapt the same loop to search an array of String values.
  • Decide when linear search is a good choice.

Written Explanation

The idea

Think of looking for a book on an unsorted shelf. You start at one end, check each book, and stop when you find yours. If you reach the other end, it is not there.

In steps:

  1. Start at index 0.
  2. Compare the element at this index with the target.
  3. If they are equal, stop and report this index.
  4. Otherwise move to the next index.
  5. If there are no more elements, report "not found".

The code

java
static int linearSearch(int[] a, int target) {
    for (int i = 0; i < a.length; i++) {
        if (a[i] == target) return i;
    }
    return -1;
}

Three details:

  • The method returns the index, not the value. The caller already knows the value; the index tells where it is.
  • return i; inside the loop ends the whole method at once, so we stop looking after the first match.
  • return -1; is reached only if the loop finished without finding the target. Valid array indexes start at 0, so -1 can never be mistaken for a real position. This is the convention used by many Java methods. The calling code must check for it:
java
int pos = linearSearch(ids, 1093);
System.out.println(pos >= 0 ? "found at " + pos : "not found");

Comparing strings

For int we compare with ==. For String values you learned that == is the wrong tool and that equals compares the text. The same loop works with a small change, here ignoring upper and lower case:

java
static int linearSearch(String[] a, String target) {
    for (int i = 0; i < a.length; i++) {
        if (a[i].equalsIgnoreCase(target)) return i;
    }
    return -1;
}

Two methods with the same name but different parameter types are legal: this is overloading from the methods module. Java picks the right one from the argument types.

Counting comparisons

The work of the loop is the comparison a[i] == target. How many happen depends on where the target is. For an array of n elements:

SituationComparisons
Best case: target is first1
Worst case: target is last, or not presentn
Typical successful searchsomewhere between, about n / 2 if every position is equally likely

The worst case is the number to remember, because it is what you must be ready for. It is also easy to state: with 1,000 elements, 1,000 comparisons. Double the data and the worst case doubles.

To measure it instead of guessing, add a counter. A counter field makes the idea visible:

java
static int comparisons = 0;

static int countedSearch(int[] a, int target) {
    comparisons = 0;
    for (int i = 0; i < a.length; i++) {
        comparisons++;
        if (a[i] == target) return i;
    }
    return -1;
}

Duplicates and edge cases

  • Duplicates. If the target appears more than once, this version returns the first index, because it stops at the first match. To find the last, loop from the end.
  • Empty array. a.length is 0, the loop body never runs, and the method returns -1. Correct, with no special code.
  • One element. Works as normal.
  • Not found. Returns -1 after checking every element.

When linear search is the right choice

  • The array is small. For ten items, nothing faster is worth the extra code.
  • The data is not sorted and you search only once or twice. Sorting first would cost more than the search.
  • You want the first match in the original order.

When the array is large, sorted, and searched many times, a better algorithm exists. That is the next lesson.

Examples

Example 1: finding a value (simple)

java
int[] data = {14, 3, 27, 9, 3, 18};
System.out.println(linearSearch(data, 27));
System.out.println(linearSearch(data, 3));
System.out.println(linearSearch(data, 99));
System.out.println(linearSearch(new int[]{}, 5));

Output:

text
2
1
-1
-1

The second line shows the duplicate rule: 3 appears at indexes 1 and 4, and the method reports the first. The last line is the empty-array edge case.

Trace for target 27:

ia[i]a[i] == 27?
014no
13no
227yes, return 2

Example 2: counting the best and worst case (practical)

java
countedSearch(data, 99);
System.out.println(comparisons);
countedSearch(data, 14);
System.out.println(comparisons);

Output:

text
6
1

The array has 6 elements. A missing target costs all 6 comparisons (the worst case), and a target in the first position costs 1 (the best case). Doubling the array to 12 elements would double the worst case to 12.

Example 3: searching names, ignoring case (realistic)

A grade-book program stores names in an array and the teacher types a name to look up:

java
String[] names = {"Adam", "Mona", "Sara"};
System.out.println(linearSearch(names, "mona"));
System.out.println(linearSearch(names, "Omar"));

Output:

text
1
-1

"mona" matches "Mona" because of equalsIgnoreCase. The caller turns the index into a friendly message, and -1 into "no such student". The student arrays from the arrays module were searched in exactly this way.

Backend Insight

Looking for a record by id, email, or username is the most common operation in a backend. If the records sit in an unsorted list, a linear search is what happens: the program checks them one after another. That is fine for a hundred records and a problem for ten million records searched on every request.

Databases solve this by building an index, a separate sorted structure that lets them jump to the right place instead of scanning every row. When someone says "this query does a full table scan", they are describing a linear search over the whole table. You do not need the details now. You only need to recognise the pattern: checking every item is simple, and it gets slower in step with the data.

Common Mistakes

Mistake 1: Returning -1 inside the loop

java
for (int i = 0; i < a.length; i++) {
    if (a[i] == target) return i;
    else return -1;      // wrong
}

This returns -1 after checking only the first element. "Not found" is known only after the loop has checked everything, so return -1; belongs after the loop.

Mistake 2: Off-by-one loop bounds

  • Incorrect: i <= a.length (reads a[a.length], which does not exist and throws ArrayIndexOutOfBoundsException).
  • Incorrect: i < a.length - 1 (never checks the last element, so a target in the last position is reported missing).
  • Correct: i < a.length.

Mistake 3: Comparing strings with ==

For String targets use equals or equalsIgnoreCase. == compares whether two names refer to the same object, not whether the text matches, and gives confusing results.

Mistake 4: Forgetting to check for -1

Using the result directly as an index, for example data[linearSearch(data, 99)], throws an exception when the target is missing. Always test pos >= 0 first.

Exercises

Try each exercise yourself before opening the solutions.

Level A: Foundation

A1. What does linearSearch return for {5, 8, 2} and target 2? For target 7?

Show solution A1

A1. For target 2 it returns 2 (the index of the 2). For target 7 it returns -1.

A2. Why is -1 used for "not found" and not 0?

Show solution A2

A2. 0 is a valid index (the first element), so returning it for "not found" would be confused with "found at the start". -1 can never be a real index.

A3. How many comparisons does a worst-case linear search make on 250 elements?

Show solution A3

A3. 250 comparisons.

Level B: Application

B1. Write static int lastIndexOf(int[] a, int target) that returns the last position of the target, or -1.

Show solution B1

B1.

java
static int lastIndexOf(int[] a, int target) {
    for (int i = a.length - 1; i >= 0; i--) {
        if (a[i] == target) return i;
    }
    return -1;
}

On {14, 3, 27, 9, 3, 18} with target 3 it returns 4.

B2. Write static int countMatches(int[] a, int target) that returns how many times the target appears. What does it return for an empty array?

Show solution B2

B2.

java
static int countMatches(int[] a, int target) {
    int count = 0;
    for (int v : a) {
        if (v == target) count++;
    }
    return count;
}

For an empty array it returns 0, because the loop never runs.

B3. Trace linearSearch on {9, 4, 7, 4} for target 7 with a table of i, a[i], and whether it matched.

Show solution B3

B3.

ia[i]match?
09no
14no
27yes, return 2

Level C: Challenge

C1. Write static int[] allIndexes(int[] a, int target) that returns every index where the target appears, as a new array (empty if none). Test with {14, 3, 27, 9, 3, 18} and target 3.

Show solution C1

C1.

java
static int[] allIndexes(int[] a, int target) {
    int count = 0;
    for (int v : a) {
        if (v == target) count++;
    }
    int[] result = new int[count];
    int k = 0;
    for (int i = 0; i < a.length; i++) {
        if (a[i] == target) result[k++] = i;
    }
    return result;
}

Run on {14, 3, 27, 9, 3, 18} with target 3, Arrays.toString prints [1, 4]; with target 5 it prints []. The first loop counts so that we know how big the result array must be (arrays have a fixed size).

C2. A friend says: "Linear search on a sorted array can stop early." Describe how, for an array sorted ascending, and say what that changes in the worst case.

Show solution C2

C2. If the array is sorted ascending, stop as soon as a[i] > target, because every later element is even larger and cannot be the target. For missing targets this can save steps. The worst case does not change: a target bigger than everything still forces all n comparisons.

Mini Challenge

Write a small program with an array of at least eight order ids (not sorted). Ask the user (with Scanner) for an id, call linearSearch, and print either "Order found at position X" or "Order not found". Run it for the first element, the last element, a missing id, and an id typed twice in the array. Write down how many comparisons your counter reports in each case.

Check your work: the not-found case prints the message and does not crash, and the counts match the best and worst cases from the table.

Summary & Next Lesson

Key takeaways

  • Linear search checks elements from index 0 in order and returns the index of the first match, or -1.
  • -1 is safe as "not found" because it is never a valid index. Callers must check for it.
  • It works on any array, sorted or not, and handles the empty array without special code.
  • Worst case (last or missing target): n comparisons. Double the data, double the work.
  • It is a good choice for small arrays and one-off searches, and it is the baseline for comparing faster methods.

Next lesson

The next lesson, "Binary search", shows how to find a value in a sorted array in about ten steps for a thousand items, by discarding half of the remaining elements at each look.

Self-check

  1. What does linearSearch return when the target is absent?
  2. Where must return -1; be placed in the method?
  3. How many comparisons does the worst case need for n elements?
  4. If the target appears twice, which index is returned?
  5. Name one situation where linear search is a good choice.
Show answers
  1. -1.
  2. After the loop, so that every element has been checked first.
  3. n.
  4. The first one, because the method returns at the first match.
  5. A small array, or an unsorted array that is searched only once or twice.

References

  • Oracle, Arrays (Java SE 21 API). The library's own binarySearch also reports "not found" with a negative number, which supports the idea that a negative return signals absence; -1 for linear search is a common course convention rather than a language rule.
  • The comparison counts and the typical-case estimate of about n / 2 are simple counting arguments, and the code outputs shown were produced by compiling and running the examples on JDK 21.
  • The database "full table scan" and index remark in Backend Insight is a general description that was not checked against a specific database manual.

Practice

Apply this lesson with the module's lab, exercises and quiz.

Lab and exercises Quiz

Marking a lesson complete is optional and you can undo it any time. Your progress stays in this browser.

Continue to next lesson

Type to search levels, phases, modules and lessons.