Remove Duplicates from Array

Java coding interview problem for Array Coding: Remove Duplicates from Array.


title: Remove Duplicates from an Array in Java – 5 Interview Approaches with Complete Explanation description: Learn how to remove duplicate elements from an array in Java using HashSet, LinkedHashSet, Sorting, Two Pointer, and Java Streams with complete Java examples, dry runs, complexity analysis, interview tips, and real-world applications. author: CodeWithVenu category: Data Structures & Algorithms tags:

  • Java
  • Arrays
  • HashSet
  • LinkedHashSet
  • Two Pointer
  • Sorting
  • DSA
  • Coding Interview

Remove Duplicates from an Array in Java

Removing duplicates from an array is one of the most common Java array interview questions.

This problem tests your understanding of:

  • Arrays
  • Hashing
  • Sorting
  • Sets
  • Two Pointer Technique
  • Data Transformation
  • Time Complexity
  • Space Complexity

Although the problem looks simple, it introduces important concepts used in many advanced problems:

  • Remove duplicate characters from String
  • Unique elements
  • Frequency counting
  • Data cleansing
  • Database deduplication
  • Stream processing

What Does Removing Duplicates Mean?

Removing duplicates means keeping only the unique values from an array.

Example:

Input

[10, 20, 10, 30, 20, 40]

Unique values:

[10, 20, 30, 40]

Duplicate values:

10

20

Why is This Question Asked in Interviews?

Interviewers ask this problem because it evaluates your knowledge of:

  • HashSet
  • LinkedHashSet
  • Sorting
  • Two Pointer Algorithm
  • Array manipulation
  • Memory optimization

It also checks whether you understand the difference between:

  • Maintaining order
  • Improving performance
  • Reducing memory usage

Real-World Applications

Removing duplicates is used in many real-world systems.


Database Data Cleaning

Customer records:

Customer ID

101

102

101

103

After removing duplicates:

101

102

103

User Analytics

Website visits:

User IDs

1001

1002

1001

1003

Unique users:

1001

1002

1003

Search Systems

Remove duplicate search results.

Example:

Java Tutorial

Java Tutorial

Spring Boot Guide

Result:

Java Tutorial

Spring Boot Guide

Recommendation Systems

Avoid recommending the same item multiple times.


Data Migration

Remove duplicate records before moving data between systems.


Problem Statement

Given an integer array,

remove duplicate elements and return an array containing only unique values.


Example 1

Input:

[1, 2, 2, 3, 4, 4, 5]

Output:

[1, 2, 3, 4, 5]

Example 2

Input:

[10, 10, 10]

Output:

[10]

Example 3

Input:

[5, 4, 3, 2, 1]

Output:

[5, 4, 3, 2, 1]

Example 4

Input:

[]

Output:

[]

Understanding Duplicate Removal

Consider:

[5, 2, 5, 3, 2, 8]

Start:

Unique = []

Read:

5

Add:

[5]

Read:

2

Add:

[5,2]

Read:

5

Already exists.

Ignore.


Read:

3

Add:

[5,2,3]

Read:

2

Already exists.

Ignore.


Read:

8

Add:

[5,2,3,8]

Final:

[5,2,3,8]

Mathematical Concept

Number of unique elements:

Total Elements - Duplicate Occurrences

Example:

[1,2,2,3,3,3]

Total:

6

Unique:

3

Array Visualization

Input:

[10,20,10,30,20]

Traversal:

10

↓

Add

[10]
20

↓

Add

[10,20]
10

↓

Already Exists

Ignore
30

↓

Add

[10,20,30]
20

↓

Already Exists

Ignore

Result:

[10,20,30]

Dry Run

Input:

[4,5,4,6,5,7]
Element Unique Collection Action
4 [4] Add
5 [4,5] Add
4 [4,5] Ignore
6 [4,5,6] Add
5 [4,5,6] Ignore
7 [4,5,6,7] Add

Output:

[4,5,6,7]

Approach 1 — Using HashSet (Recommended)

The simplest and most commonly used approach is using a HashSet.

A HashSet:

  • Does not allow duplicates.
  • Provides average O(1) lookup.
  • Automatically removes duplicate values.

Algorithm

  1. Create a HashSet.
  2. Traverse the array.
  3. Add every element to the HashSet.
  4. Convert Set back to an array.
  5. Return result.

Java Program

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class RemoveDuplicatesHashSet {

    public static int[] removeDuplicates(int[] numbers) {

        Set<Integer> unique =
                new HashSet<>();

        for (int number : numbers) {

            unique.add(number);

        }

        return unique.stream()
                .mapToInt(Integer::intValue)
                .toArray();

    }

    public static void main(String[] args) {

        int[] numbers =
                {1, 2, 2, 3, 4, 4, 5};

        System.out.println(
                Arrays.toString(
                        removeDuplicates(numbers)));

    }

}

Output

[1, 2, 3, 4, 5]

Step-by-Step Code Explanation

Create HashSet:

Set<Integer> unique =
        new HashSet<>();

Traverse array:

for(int number : numbers)

Add elements:

unique.add(number);

Duplicate values are automatically ignored.


Convert Set to array:

toArray()

Dry Run Using HashSet

Input:

[1,2,2,3]

Initially:

{}

Add:

1

{1}

Add:

2

{1,2}

Add duplicate:

2

{1,2}

Add:

3

{1,2,3}

Result:

[1,2,3]

Advantages

  • Very simple implementation.
  • Average O(1) insertion.
  • Handles unsorted arrays.
  • Good production solution.
  • Removes duplicates automatically.

Drawbacks

  • Does not preserve original order.
  • Requires extra memory.
  • Hashing overhead.

Approach 2 — Using LinkedHashSet (Preserve Order)

LinkedHashSet is similar to HashSet.

The difference:

It maintains insertion order.

Example:

Input:

[5,2,5,3,2]

HashSet output:

[2,3,5]

Possible order change.

LinkedHashSet output:

[5,2,3]

Original order preserved.


Algorithm

  1. Create LinkedHashSet.
  2. Add array elements.
  3. Convert back to array.

Java Program

import java.util.*;

public class RemoveDuplicatesLinkedHashSet {

    public static Integer[] removeDuplicates(
            Integer[] numbers) {

        Set<Integer> unique =
                new LinkedHashSet<>();

        for (int number : numbers) {

            unique.add(number);

        }

        return unique.toArray(
                new Integer[0]);

    }

    public static void main(String[] args) {

        Integer[] numbers =
                {5,2,5,3,2};

        System.out.println(
                Arrays.toString(
                        removeDuplicates(numbers)));

    }

}

Output

[5, 2, 3]

Step-by-Step Explanation

Create LinkedHashSet:

Set<Integer> unique =
        new LinkedHashSet<>();

Insert elements:

unique.add(number);

Duplicates removed automatically.


Order maintained:

First appearance order

Advantages

  • Removes duplicates.
  • Preserves insertion order.
  • Easy to understand.
  • Better than HashSet when order matters.

Drawbacks

  • More memory than HashSet.
  • Slightly slower because it maintains linked structure.

Time & Space Complexity

Approach Time Space
HashSet O(n) O(n)
LinkedHashSet O(n) O(n)

Where:

n = Number of elements

Comparison

Feature HashSet LinkedHashSet
Duplicate Removal ✅ ✅
Maintains Order ❌ ✅
Performance Faster Slightly slower
Memory Less More

Advantages Summary

HashSet

  • Fast lookup.
  • Simple.
  • Good for general use.

LinkedHashSet

  • Keeps original order.
  • Better for user-facing output.

Drawbacks Summary

HashSet

  • Random ordering.

LinkedHashSet

  • Additional memory overhead.

Approach 3 — Using Sorting

Sorting is another common approach to remove duplicates.

The idea is:

  1. Sort the array.
  2. Duplicate values become adjacent.
  3. Keep only values that are different from the previous value.

Example

Input:

[5, 2, 8, 2, 5, 1]

After sorting:

[1, 2, 2, 5, 5, 8]

Compare adjacent elements:

1 → Keep

2 → Keep

2 → Duplicate

5 → Keep

5 → Duplicate

8 → Keep

Result:

[1,2,5,8]

Algorithm

  1. Sort the array.
  2. Create a result collection.
  3. Compare current element with previous element.
  4. Add only unique values.
  5. Return the result.

Java Program

import java.util.*;

public class RemoveDuplicatesSorting {

    public static int[] removeDuplicates(int[] numbers) {

        Arrays.sort(numbers);

        List<Integer> unique =
                new ArrayList<>();

        unique.add(numbers[0]);

        for (int i = 1; i < numbers.length; i++) {

            if (numbers[i] != numbers[i - 1]) {

                unique.add(numbers[i]);

            }

        }

        return unique.stream()
                .mapToInt(Integer::intValue)
                .toArray();

    }

    public static void main(String[] args) {

        int[] numbers =
                {5, 2, 8, 2, 5, 1};

        System.out.println(
                Arrays.toString(
                        removeDuplicates(numbers)));

    }

}

Output

[1, 2, 5, 8]

Step-by-Step Explanation

Sort array:

Arrays.sort(numbers);

Input:

5 2 8 2 5 1

After sorting:

1 2 2 5 5 8

Compare elements:

if(numbers[i] != numbers[i-1])

Only add new values.


Dry Run

Input:

[4,2,4,1,3,2]

Sorted:

[1,2,2,3,4,4]
Element Previous Action
1 - Add
2 1 Add
2 2 Ignore
3 2 Add
4 3 Add
4 4 Ignore

Result:

[1,2,3,4]

Advantages

  • Simple logic.
  • No hashing required.
  • Useful when sorted output is acceptable.
  • Easy duplicate detection.

Drawbacks

  • Sorting changes original order.
  • Time complexity increases.
  • Not suitable when order must be preserved.

Approach 4 — Two Pointer Approach (Optimal for Sorted Arrays)

The Two Pointer technique is the most efficient approach when the array is already sorted.

It removes duplicates in-place without extra memory.


Important Requirement

The array must already be sorted.

Example:

Valid:

[1,1,2,2,3,4]

Invalid:

[3,1,2,1]

Two Pointer Concept

Use two indexes:

i → Position of unique element

j → Traversing element

Visualization

Input:

[1,1,2,2,3]

Initial:

i = 0

j = 1

Compare:

numbers[j]

with

numbers[i]

If different:

Move i.

Copy value.


Final:

[1,2,3]

Algorithm

  1. Start i = 0.
  2. Traverse array using j.
  3. If current element differs from previous unique element:
    • Increase i.
    • Store value at index i.
  4. Return elements from index 0 to i.

Java Program

import java.util.Arrays;

public class RemoveDuplicatesTwoPointer {

    public static int removeDuplicates(int[] numbers) {

        if (numbers.length == 0) {
            return 0;
        }

        int i = 0;

        for (int j = 1; j < numbers.length; j++) {

            if (numbers[j] != numbers[i]) {

                i++;

                numbers[i] = numbers[j];

            }

        }

        return i + 1;

    }

    public static void main(String[] args) {

        int[] numbers =
                {1,1,2,2,3,4,4};

        int length =
                removeDuplicates(numbers);

        System.out.println(
                Arrays.toString(
                        Arrays.copyOf(numbers, length)));

    }

}

Output

[1, 2, 3, 4]

Step-by-Step Explanation

Input:

[1,1,2,2,3]

Initial:

i = 0

Compare:

numbers[1]

with

numbers[0]

Both are:

1

Ignore.


Compare:

2 != 1

Move:

i++

Copy:

numbers[1] = 2

Array:

[1,2,2,2,3]

Continue:

Final unique section:

[1,2,3]

Complexity

Time:

O(n)

Space:

O(1)

Advantages

  • Optimal solution.
  • No extra memory.
  • In-place modification.
  • Common interview question.

Drawbacks

  • Requires sorted input.
  • More difficult than HashSet.
  • Does not work directly on unsorted arrays.

Approach 5 — Using Java Streams

Java Streams provide a concise functional approach.

The distinct() operation automatically removes duplicates.


Algorithm

  1. Convert array to Stream.
  2. Apply distinct().
  3. Convert back to array.

Java Program

import java.util.Arrays;

public class RemoveDuplicatesStreams {

    public static int[] removeDuplicates(int[] numbers) {

        return Arrays.stream(numbers)
                .distinct()
                .toArray();

    }

    public static void main(String[] args) {

        int[] numbers =
                {1,2,2,3,4,4};

        System.out.println(
                Arrays.toString(
                        removeDuplicates(numbers)));

    }

}

Output

[1, 2, 3, 4]

Advantages

  • Very concise.
  • Modern Java style.
  • Preserves encounter order.
  • Easy to read.

Drawbacks

  • Stream overhead.
  • Less control over memory.
  • Not always preferred in algorithm interviews.

Primitive vs Object Arrays

Primitive Array

Example:

int[] numbers;

Advantages:

  • Faster.
  • Less memory.
  • No boxing.

Object Array

Example:

Integer[] numbers;

Advantages:

  • Works with Collections.
  • Supports generics.

Unsorted vs Sorted Arrays

Array Type Best Approach
Unsorted Array HashSet / LinkedHashSet
Sorted Array Two Pointer
Need Order LinkedHashSet
Need Functional Style Streams

Comparison of All Approaches

Approach Time Complexity Space Order Preserved Best Use Case
HashSet O(n) O(n) ❌ Fast duplicate removal
LinkedHashSet O(n) O(n) ✅ Preserve order
Sorting O(n log n) O(n) ❌ Sorted output
Two Pointer O(n) O(1) ✅ Sorted arrays
Streams O(n) O(n) ✅ Modern Java

Common Interview Mistakes

Mistake 1

Using Two Pointer on an unsorted array.

Wrong:

[3,1,2,3]

Two Pointer requires sorting first.


Mistake 2

Assuming HashSet preserves order.

HashSet:

No guaranteed order

Use:

LinkedHashSet

if order matters.


Mistake 3

Modifying input array accidentally.

Sorting changes:

Arrays.sort(numbers);

Mistake 4

Ignoring empty arrays.

Always check:

if(numbers.length == 0)

Mistake 5

Confusing duplicate removal with frequency counting.

These are different problems.


Edge Cases

Input Output
[] []
[1] [1]
[1,1,1] [1]
[1,2,3] [1,2,3]
[-1,-1,2] [-1,2]

Interview Follow-up Questions

Q1. Remove duplicates without extra memory.

Q2. Remove duplicates from a sorted array.

Q3. Preserve original order.

Q4. Remove duplicates from a String.

Q5. Count duplicate elements.

Q6. Find elements appearing more than once.

Q7. Remove duplicates from a linked list.

Q8. How does HashSet remove duplicates internally?

Q9. Can this be solved using streams?

Q10. What approach works best for millions of records?


Related Problems

  • Check Unique Characters
  • Remove Duplicate Characters from String
  • Character Frequency
  • Find Duplicate Numbers
  • First Repeating Element
  • First Non-Repeating Element
  • Two Sum
  • Intersection of Arrays

Key Takeaways

  • HashSet is the simplest solution for removing duplicates.
  • LinkedHashSet preserves insertion order.
  • Sorting groups duplicates together.
  • Two Pointer is the optimal O(1) space solution for sorted arrays.
  • Streams provide concise modern Java syntax.
  • Always choose the approach based on requirements:
Need speed?
→ HashSet

Need order?
→ LinkedHashSet

Sorted array?
→ Two Pointer

Need no extra space?
→ Two Pointer

Frequently Asked Interview Questions

Q1. What is the best approach?

It depends on the input.

For general arrays:

HashSet

For sorted arrays:

Two Pointer

Q2. Why is Two Pointer better?

It removes duplicates in-place:

Time: O(n)

Space: O(1)

Q3. Does HashSet maintain order?

No.

Use:

LinkedHashSet

for insertion order.


Q4. Why sort before removing duplicates?

Sorting places duplicates next to each other, making comparison easier.


Q5. Which approach should be used in production?

Choose based on requirements:

  • Data cleaning → HashSet
  • User-facing ordered output → LinkedHashSet
  • Memory-sensitive sorted data → Two Pointer

Interview Tip

If asked:

"Remove duplicates from an array."

Start by clarifying:

  1. Is the array sorted?
  2. Should original order be maintained?
  3. Can extra memory be used?

Then choose:

  1. HashSet (general solution)
  2. LinkedHashSet (preserve order)
  3. Two Pointer (sorted + optimal memory)
  4. Streams (modern Java)

Explaining these trade-offs demonstrates strong understanding of Java Collections, algorithms, and production-level decision making.