Advertisement
Home Data Structure Arrays Check if an Array Contains Any Duplicates

Check if an Array Contains Any Duplicates

0
Advertisement

Title: Check if an Array Contains Any Duplicates

In this guide, you’ll learn how to check whether a Java array contains any duplicate elements. This is one of the most common warm-up questions in coding interviews, and it’s a great way to practice choosing the right data structure for a membership check.

Understanding the Problem

Given an array of integers, the goal is to return true if any value appears more than once, and false if every value is unique. We’ll build a HashSet-based solution, trace it step by step, and cover the edge cases an interviewer would expect you to mention.

Approach

  1. Create an empty HashSet<Integer> named seen to track every value you’ve already visited.
  2. Iterate over the input array one element at a time using a for-each loop.
  3. For each element, call seen.add(number) and check its return value.
  4. If add() returns false, the value was already in the set, so return true immediately.
  5. If the loop completes without that happening, no duplicates exist, so return false.

Java Program

Java
import java.util.HashSet;
import java.util.Set;

public class DuplicateChecker {

    public static boolean containsDuplicate(int[] numbers) {
        Set<Integer> seen = new HashSet<>();
        for (int number : numbers) {
            if (!seen.add(number)) {
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        int[] numbers = {4, 3, 2, 7, 8, 2, 1};
        boolean hasDuplicates = containsDuplicate(numbers);
        System.out.println("Array contains duplicates: " + hasDuplicates);
    }
}

Explanation of the Program

The method containsDuplicate declares a HashSet<Integer> named seen to remember every value it has visited so far. A HashSet is the right choice here because its add() and contains() operations run in constant time on average, unlike a List, whose contains() scans every element.

Inside the loop, seen.add(number) does two things at once: it inserts number into the set, and it returns false if that value was already present. Negating the result with ! lets the method return true the instant it finds a repeat, without scanning the rest of the array.

If the loop finishes without ever hitting that condition, every element was unique, so the method falls through to return false. The main method demonstrates this on a small array that contains the value 2 twice.

Step-by-Step Trace

For the array [5, 9, 3, 9, 1], the method should return true because the value 9 appears twice. The table below shows the state of seen before each call to add(), and whether that call succeeds.

Iterationnumbers[i]seen (before)add() returnsDuplicate found?
15{}trueNo
29{5}trueNo
33{5, 9}trueNo
49{5, 9, 3}falseYes, loop exits

Before processing index i, seen holds exactly the distinct values from numbers[0..i-1]; the loop returns true the moment add() reports that the current value is already present.

Examples

Example 1: No Duplicates

This array contains five distinct values, so the method scans the whole array and returns false.

Java
int[] numbers = {10, 20, 30, 40, 50};
System.out.println(containsDuplicate(numbers));
// Output: false

Example 2: Duplicate in the Middle

Here the value 2 repeats at index 3, so add() fails on that element and the method returns true right away.

Java
int[] numbers = {1, 2, 3, 2, 5};
System.out.println(containsDuplicate(numbers));
// Output: true

Example 3: Single-Element Array

A one-element array can never contain a duplicate, so the loop runs once, add() succeeds, and the method returns false.

Java
int[] numbers = {42};
System.out.println(containsDuplicate(numbers));
// Output: false

Common Mistakes to Avoid

These are the mistakes candidates most often make when solving this problem under interview pressure.

  • Using brute-force nested loops without an early exit – comparing every pair with two nested loops costs O(n squared), and if you forget to return as soon as a match is found, you keep comparing pairs that no longer matter. Return true immediately inside the inner loop instead of setting a flag and continuing.
  • Sorting the array in place to detect duplicates – calling Arrays.sort(numbers) directly on the caller’s array silently reorders it, which breaks any code that depends on the original order. Clone the array first with numbers.clone() if sorting is the approach you want.
  • Calling contains() then add() as two separate steps – checking seen.contains(number) before calling seen.add(number) does two lookups where one would do. Rely on the boolean that add() already returns.
  • Using a List instead of a Set for the seen collection – an ArrayList‘s contains() scans every element, turning an O(n) solution into O(n squared) on arrays with many unique values. Use a HashSet so membership checks stay O(1) on average.

Edge Cases to Test

Walk through these inputs before you call the solution finished.

  • Empty array
  • Single-element array
  • All identical elements
  • Array already sorted
  • Duplicate at the last index
  • Negative numbers and zero mixed together
  • Integer.MIN_VALUE and Integer.MAX_VALUE present
  • Null array reference

Additional Considerations

The HashSet approach runs in O(n) time because each element triggers one constant-time add() call, and it uses O(n) extra space in the worst case, when every element is unique and ends up stored in the set.

An alternative is to sort the array first and scan for adjacent equal values, which costs O(n log n) time but can run in O(1) extra space if sorting in place is acceptable. Choose the HashSet version when you need to preserve the original array order or when you’re processing values as a stream rather than a fixed array.

The edge case list above includes Integer.MIN_VALUE and Integer.MAX_VALUE because this method only ever compares values for equality, never arithmetic, so there’s no overflow risk the way there would be in a sum-based duplicate check. A null array reference, on the other hand, throws a NullPointerException at the for-each loop, so validate the input before calling containsDuplicate if null is a realistic caller input.

Interview Follow-up Questions

Once you’ve nailed the base solution, expect an interviewer to push further with questions like these.

  • What if the array is already sorted? – compare each element to its neighbor in a single O(n) pass with no extra space, since duplicates in a sorted array always sit next to each other.
  • What if you need the duplicate values themselves, not just a boolean? – keep the same HashSet loop, but instead of returning immediately, add each failed value to a result list and keep scanning.
  • What if the input arrives as a stream of unknown length? – keep inserting into the set as values arrive and report a duplicate the moment an add() call fails, without ever buffering the whole stream in memory.
  • What if the array holds billions of elements and must be checked with bounded extra memory? – trade exactness for space with a Bloom filter, which accepts a small false-positive rate in exchange for sublinear memory use, or partition the data and use external sorting to bring equal values together.

Conclusion

Checking an array for duplicates is a small problem with a lot to teach: picking the right collection, understanding the cost of each operation, and reasoning about edge cases before you’re asked to. The HashSet solution above is the version most interviewers expect, and it scales cleanly to the follow-up variations covered here.

Try adapting the code to return the duplicate values instead of a boolean, or to work against a List<Integer> instead of an int[], as practice for the kind of small twists interviewers like to add. You can learn more about array-based problems like this one in our Arrays category.