Check Unique Characters

Java coding interview problem for Character Problems: Check Unique Characters.

Checking whether a string contains all unique characters is one of the most frequently asked Java String interview questions.

Although it appears simple, this problem tests your understanding of:

  • String Traversal
  • HashSet
  • Arrays
  • Bit Manipulation
  • Time Complexity
  • Space Complexity
  • Character Encoding

This question is commonly asked by companies like Amazon, Microsoft, Google, Oracle, IBM, Adobe, Walmart, and many product-based companies.

Mastering this problem also helps solve advanced interview questions such as:

  • Remove Duplicate Characters
  • First Non-Repeating Character
  • Character Frequency
  • Detect Duplicate Characters
  • Longest Substring Without Repeating Characters

Problem Statement

Given a string,

determine whether every character appears exactly once.

Return

  • true if all characters are unique.
  • false if any character repeats.

Example 1

Input

abcdef

Output

true

Explanation

a b c d e f

All characters are unique.

Example 2

Input

hello

Output

false

Explanation

l appears twice.

Example 3

Input

Java

Output

false

Explanation

a appears twice.

Example 4

Input

12345

Output

true

Example 5

Input

abca

Output

false

What are Unique Characters?

A string contains unique characters if no character is repeated.

Example

Unique

Python

Characters

P

y

t

h

o

n

Every character occurs exactly once.


Not Unique

banana

Frequency

b → 1

a → 3

n → 2

Repeated characters exist.


Why is this Question Asked in Interviews?

Interviewers use this question to evaluate your understanding of:

  • HashSet
  • Hashing
  • Arrays
  • Bit Manipulation
  • String Traversal
  • Character Encoding
  • Time Complexity
  • Space Complexity

This problem has multiple optimal solutions, making it ideal for interview discussions.


Real-World Applications

Checking unique characters is useful in many real-world applications.


Username Validation

Ensure usernames contain unique identifiers.

Example

venu123

Password Analysis

Detect repeated characters in passwords.

Example

Pass@123

Data Validation

Ensure IDs contain no duplicate symbols.


License Key Verification

Example

ABCD-1234

Verify uniqueness if required.


DNA Sequence Analysis

Identify repeated nucleotide patterns.


Cryptography

Validate uniqueness of generated keys or tokens.


Understanding Character Uniqueness

Input

apple

Read one character at a time.


Read

a

Store

Seen = {a}

Read

p

Store

Seen = {a,p}

Read

p

Already exists.

Duplicate found.

Return

false

No need to continue.


ASCII Visualization

Input

code
c

↓

Not Seen

↓

Store
o

↓

Not Seen

↓

Store
d

↓

Not Seen

↓

Store
e

↓

Not Seen

↓

Store

Result

Unique

Input

hello
h

↓

Store
e

↓

Store
l

↓

Store
l

↓

Already Present

↓

Duplicate Found

Return

false

Mathematical Concept

If

Length of String

=

Number of Distinct Characters

then

All Characters Are Unique

Otherwise

Duplicate Exists

Example

apple

Length = 5

Distinct = 4

Since

5 ≠ 4

Result

Not Unique

Dry Run

Input

world
Character Seen Characters Duplicate?
w {w} No
o {w,o} No
r {w,o,r} No
l {w,o,r,l} No
d {w,o,r,l,d} No

Result

true

Input

apple
Character Seen Characters Duplicate?
a {a} No
p {a,p} No
p Already Present Yes

Return

false

Approach 1 — Using HashSet (Recommended)

The easiest and most common interview solution is using a HashSet.

A HashSet stores only unique elements.

Whenever we try to insert an already existing character,

add() returns false.


Algorithm

  1. Create a HashSet.
  2. Traverse the string.
  3. Insert each character.
  4. If insertion fails, duplicate found.
  5. Return false.
  6. Otherwise return true.

Java Program

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

public class UniqueCharactersHashSet {

    public static boolean isUnique(String text) {

        Set<Character> seen = new HashSet<>();

        for (char ch : text.toCharArray()) {

            if (!seen.add(ch)) {
                return false;
            }

        }

        return true;

    }

    public static void main(String[] args) {

        System.out.println(isUnique("abcdef"));

        System.out.println(isUnique("apple"));

    }

}

Output

true

false

Step-by-Step Code Explanation

Create HashSet

Set<Character> seen =
        new HashSet<>();

Traverse every character

for(char ch : text.toCharArray())

Insert character

seen.add(ch)

If already exists

return false;

Otherwise

Continue traversal.

Finally

return true;

Dry Run of HashSet Approach

Input

Java
Character HashSet Result
J {J} Continue
a {J,a} Continue
v {J,a,v} Continue
a Already Exists Return false

Advantages

  • Very easy to understand.
  • Excellent interview solution.
  • Supports Unicode.
  • Stops immediately after finding the first duplicate.
  • Average lookup time is O(1).

Drawbacks

  • Requires extra memory.
  • Uses hashing internally.

Approach 2 — Using Boolean Array (ASCII)

If the input contains only ASCII characters, a Boolean array is faster than a HashSet.

Each array index represents one ASCII character.

Example

visited['A']

visited['a']

visited['0']

Visualization

Input

cat

Initially

visited[]

↓

All false

Read

c
visited['c'] = true

Read

a
visited['a'] = true

Read

t
visited['t'] = true

No duplicates.


Algorithm

  1. Create Boolean array of size 256.
  2. Traverse the string.
  3. If character already visited, return false.
  4. Otherwise mark it visited.
  5. Return true.

Java Program

public class UniqueCharactersBooleanArray {

    public static boolean isUnique(String text) {

        boolean[] visited = new boolean[256];

        for (char ch : text.toCharArray()) {

            if (visited[ch]) {
                return false;
            }

            visited[ch] = true;

        }

        return true;

    }

    public static void main(String[] args) {

        System.out.println(isUnique("world"));

        System.out.println(isUnique("hello"));

    }

}

Output

true

false

Step-by-Step Code Explanation

Create Boolean array

boolean[] visited =
        new boolean[256];

Traverse string

for(char ch : text.toCharArray())

Check

visited[ch]

If true

Duplicate Found

Otherwise

visited[ch] = true;

Continue.


Time & Space Complexity

Approach Time Extra Space
HashSet O(n) O(k)
Boolean Array (ASCII) O(n) O(1)*

Where

  • n = Length of the string
  • k = Number of distinct characters

Note: For ASCII input, the Boolean array has a fixed size of 256, so its space complexity is considered O(1).


Comparison of Approaches

Feature HashSet Boolean Array
Interview Friendly ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Performance ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
Unicode Support ✅ ❌
Implementation Easy Easy

Advantages

  • Both approaches provide O(n) time complexity.
  • HashSet supports Unicode and dynamic character sets.
  • Boolean Array is extremely fast for ASCII input.
  • Both stop immediately when a duplicate is found.

Drawbacks

  • HashSet requires additional memory.
  • Boolean Array works only for ASCII characters.
  • Neither approach demonstrates bit-level optimization.

Approach 3 — Using Bit Manipulation (Most Optimized)

Bit Manipulation is one of the most optimized solutions for this problem.

Instead of using a HashSet or Boolean array,

we use a single integer (or long) where each bit represents one character.

This approach is commonly asked in interviews when the input contains only lowercase English letters (a-z).


Why Bit Manipulation?

For lowercase English letters:

a → Bit 0

b → Bit 1

c → Bit 2

...

z → Bit 25

Each bit indicates whether a character has already been seen.


Visualization

Input

abc

Initially

00000000000000000000000000

Read

a
00000000000000000000000001

Read

b
00000000000000000000000011

Read

c
00000000000000000000000111

No duplicate found.


Input

aba

When reading the second

a

Bit is already set.

Return

false

Algorithm

  1. Initialize an integer mask to 0.
  2. Traverse the string.
  3. Compute bit position.
  4. Check if bit is already set.
  5. If yes, duplicate found.
  6. Otherwise set the bit.
  7. Return true if traversal completes.

Java Program

public class UniqueCharactersBitMask {

    public static boolean isUnique(String text) {

        int mask = 0;

        for (char ch : text.toCharArray()) {

            int bit = ch - 'a';

            if ((mask & (1 << bit)) != 0) {
                return false;
            }

            mask |= (1 << bit);

        }

        return true;

    }

    public static void main(String[] args) {

        System.out.println(isUnique("world"));

        System.out.println(isUnique("hello"));

    }

}

Output

true

false

Dry Run

Input

cat
Character Bit Position Mask (Binary) Duplicate
c 2 00000100 No
a 0 00000101 No
t 19 10000000000000000101 No

Advantages

  • Fastest solution.
  • Constant extra space.
  • Excellent interview discussion.
  • Demonstrates low-level optimization.

Drawbacks

  • Works only for lowercase English letters.
  • Less readable.
  • Harder for beginners.

Approach 4 — Using Java Streams

Java Streams provide a concise functional programming solution.

The idea is simple:

  • Count distinct characters.
  • Compare with string length.

Algorithm

  1. Convert string into a Stream.
  2. Count distinct characters.
  3. Compare with original length.
  4. Return result.

Java Program

public class UniqueCharactersStreams {

    public static boolean isUnique(String text) {

        long distinct =
                text.chars()
                        .distinct()
                        .count();

        return distinct == text.length();

    }

    public static void main(String[] args) {

        System.out.println(isUnique("abcdef"));

        System.out.println(isUnique("apple"));

    }

}

Output

true

false

Advantages

  • Modern Java.
  • Very concise.
  • Functional programming style.
  • Easy to read.

Drawbacks

  • Stream overhead.
  • Less common in interviews.
  • Slightly slower than HashSet.

Approach 5 — Using Sorting

Sorting groups identical characters together.

After sorting,

we only need to compare adjacent characters.


Visualization

Input

banana

Sorted

aaabnn

Traverse

a

↓

a

Duplicate Found

Return

false

Algorithm

  1. Convert string into character array.
  2. Sort array.
  3. Compare adjacent characters.
  4. If equal, duplicate found.
  5. Otherwise continue.
  6. Return true.

Java Program

import java.util.Arrays;

public class UniqueCharactersSorting {

    public static boolean isUnique(String text) {

        char[] characters = text.toCharArray();

        Arrays.sort(characters);

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

            if (characters[i] == characters[i - 1]) {
                return false;
            }

        }

        return true;

    }

    public static void main(String[] args) {

        System.out.println(isUnique("world"));

        System.out.println(isUnique("hello"));

    }

}

Output

true

false

Advantages

  • No HashSet required.
  • Easy to understand.
  • Useful when sorting is already needed.

Drawbacks

  • Sorting increases time complexity.
  • Modifies character order.
  • Slower than hashing.

Unicode Considerations

Java uses UTF-16 encoding for String.

Examples

こんにちは
नमस्ते
😊

HashSet

✅ Supports Unicode.

Java Streams

✅ Supports Unicode.

Sorting

✅ Supports Unicode characters.

Boolean Array

❌ Limited to the configured array size (typically ASCII).

Bit Manipulation

❌ Limited to lowercase English letters unless significantly extended.


Edge Cases

Input Output
"" true
"a" true
"aa" false
"abcdef" true
"apple" false
"12345" true
"112345" false
"😊😊" false (HashSet/Streams/Sorting)

Time & Space Complexity

Approach Time Extra Space
HashSet O(n) O(k)
Boolean Array O(n) O(1)*
Bit Manipulation O(n) O(1)
Java Streams O(n) O(k)
Sorting O(n log n) O(1)**

Where

  • n = Length of the string
  • k = Number of distinct characters

*Boolean Array uses fixed-size ASCII storage.

**Java's Arrays.sort(char[]) uses Dual-Pivot Quicksort for primitive arrays and requires only a small recursion stack, so it is commonly treated as O(log n) auxiliary space in practice.


Comparison of All Approaches

Approach Interview Friendly Performance Unicode Support Best Use Case
HashSet ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ✅ Recommended interview solution
Boolean Array ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ❌ ASCII-only input
Bit Manipulation ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ❌ Lowercase English letters
Java Streams ⭐⭐⭐⭐ ⭐⭐⭐ ✅ Modern Java
Sorting ⭐⭐⭐⭐ ⭐⭐⭐ ✅ When sorted data is already needed

Common Interview Mistakes

Mistake 1

Using nested loops.

Wrong complexity

O(n²)

Use HashSet instead.


Mistake 2

Using Bit Manipulation for uppercase or Unicode input.

Example

Java

The bit-mask solution assumes lowercase English letters only.


Mistake 3

Ignoring empty strings.

""

contains no duplicates and should return

true

Mistake 4

Forgetting to stop early.

As soon as a duplicate is found,

return immediately.


Mistake 5

Using Sorting without mentioning complexity.

Sorting increases complexity from

O(n)

to

O(n log n)

Interview Follow-up Questions

Q1. Why is HashSet preferred?

Q2. Why is Bit Manipulation the fastest?

Q3. What assumptions does Bit Manipulation make?

Q4. Which approaches support Unicode?

Q5. Can this be solved without extra space?

Q6. Why is Sorting slower?

Q7. What happens if the string contains emojis?

Q8. Can Java Streams replace HashSet?

Q9. How would you ignore case (A and a)?

Q10. How would you check uniqueness in a file containing millions of characters?


Related Problems

  • Remove Duplicate Characters
  • Character Frequency
  • Detect Duplicate Characters
  • First Non-Repeating Character
  • Longest Substring Without Repeating Characters
  • Permutation Check
  • Group Anagrams
  • Most Frequent Character
  • Sort Characters by Frequency

Key Takeaways

  • Checking unique characters is a fundamental String interview problem.
  • HashSet is the simplest and most recommended solution.
  • Boolean Array is an optimized solution for ASCII input.
  • Bit Manipulation provides constant-space optimization for lowercase English letters.
  • Java Streams offer a concise functional programming approach.
  • Sorting is useful when the input is already being sorted, but it increases time complexity.

Frequently Asked Interview Questions

Q1. Which solution is best for interviews?

The HashSet approach is the most commonly expected answer because it is simple, readable, and works with Unicode.


Q2. Which solution is the most optimized?

For lowercase English letters only, Bit Manipulation is the most optimized because it uses constant extra space and avoids additional collections.


Q3. Why use a Boolean Array?

A Boolean Array provides very fast lookups for ASCII input and avoids hashing overhead.


Q4. Why is Sorting slower?

Sorting requires O(n log n) time before duplicate checking, whereas HashSet-based solutions complete in O(n) average time.


Q5. Can this problem be solved without additional memory?

Yes. By sorting the characters first and then checking adjacent elements, you can avoid auxiliary data structures, but the trade-off is increased time complexity.


Interview Tip

If an interviewer asks:

"How do you check whether a string contains all unique characters?"

Start with the HashSet solution because it is clear, efficient, and production-ready.

Then discuss increasingly optimized alternatives:

  1. HashSet (recommended)
  2. Boolean Array (ASCII optimization)
  3. Bit Manipulation (lowercase English letters)
  4. Java Streams (functional programming)
  5. Sorting (no hash-based structure)

Before coding, clarify:

  • Is the input limited to lowercase English letters?
  • Is it ASCII or full Unicode?
  • Are uppercase and lowercase considered different?
  • Can additional memory be used?

Discussing these assumptions and trade-offs demonstrates strong problem-solving skills and a solid understanding of Java data structures and algorithms.