Talentd
FleetCode
Make and follow sheets.Sign in

Count the Number of Special Characters II solution and explanation

MediumHash TableString5 min read60.3% acceptanceUpdated 9 Apr 2026
Count the Number of Special Characters II | Simplest Explanation | Dry Run | Leetcode 3121 | MIKcodestorywithMIK · 14:27 · 4K viewsWatch on YouTube
9 more videos on this problem
  1. Count the Number of Special Characters II | Simplest Explanation | Dry Run | Leetcode 3121 | MIKcodestorywithMIK · 14:27 · 4K views
  2. 3121 & 3120 Count the Number of Special Characters II & Characters IAryan Mittal · 14:54 · 3K views
  3. 3121. Count the Number of Special Characters II (Leetcode Medium)Programming Live with Larry · 5:08 · 241 views
  4. Daily Leetcode #2248: May 27, 2026 - 3121. Count the Number of Special Characters IIProgramming Live with Larry · 7:39 · 222 views
  5. Count the Number of Special Characters II | LeetCode 3121 - Pythonimpoldev · 6:46 · 212 views
  6. LeetCode 3121 Explained | Count Special Characters II (POTD Solution)Code Crusaders · 7:49 · 106 views
  7. 3121. Count the Number of Special Characters II | Leetcode Weekly Contest 394 | Using Map | Easy |Sucil Dey · 12:47 · 64 views
  8. 3121 Leetcode | Count the Number of Special Characters II | Daily Challenge | Easy C++ Solution 🚀 CodeSprint · 12:23 · 50 views
  9. 3121. Count the Number of Special Characters II 🚀 Easy String LogicJust Coding - Tamil · 10:04 · 46 views
  10. LeetCode 3121: Count the Number of Special Characters II | Optimal O(n) SolutionVijay Algorithms · 21:17 · 30 views

The problem

You are given a string word. A letter c is called special if it appears both in lowercase and uppercase in word, and every lowercase occurrence of c appears before the first uppercase occurrence of c.

Return the number of special letters in word.

Example 1:

Input: word = "aaAbcBC"

Output: 3

Explanation:

The special characters are 'a', 'b', and 'c'.

Example 2:

Input: word = "abc"

Output: 0

Explanation:

There are no special characters in word.

Example 3:

Input: word = "AbBCab"

Output: 0

Explanation:

There are no special characters in word.

Constraints:

  • 1 <= word.length <= 2 * 105
  • word consists of only lowercase and uppercase English letters.

Approach overview

Problem Overview: You are given a string containing uppercase and lowercase English letters. A character is considered special if both its lowercase and uppercase versions appear in the string, and every lowercase occurrence appears before the first uppercase occurrence. The task is to count how many characters satisfy this rule.

Approach 1: Using HashMaps to Track First Occurrence (O(n) time, O(1) space)

This approach scans the string while storing positional information for each character using hash maps. Track the last index where each lowercase letter appears and the first index where each uppercase letter appears. After building these maps, iterate through all 26 letters and check whether both versions exist. A character is special if the last lowercase index is strictly less than the first uppercase index. Hash lookups make each check constant time, so the full solution runs in O(n) time with O(1) extra space because the alphabet size is fixed.

This method is flexible and easy to implement in languages with strong dictionary support. It fits naturally with problems involving character tracking using a hash table and sequential scans of a string.

Approach 2: Two-Pass Array Approach (O(n) time, O(1) space)

This approach replaces hash maps with fixed-size arrays of length 26. During the first pass, record the last index of every lowercase letter and the first index of every uppercase letter. Arrays work well here because the problem only deals with English letters. In the second pass (or a simple loop over 26 characters), check the same ordering condition: lastLower[i] < firstUpper[i].

Arrays eliminate hashing overhead and are slightly faster in practice. Each character is processed once, producing O(n) time complexity with constant O(1) space. This version is common in C, C++, and C# implementations where direct indexing is faster than dictionary operations. The logic still relies on basic string traversal and index comparison.

Recommended for interviews: Interviewers usually expect the linear-time solution that records positions of lowercase and uppercase characters. The hash map version demonstrates clear reasoning about character tracking, while the array version shows optimization awareness and better constant factors. Both achieve O(n) time and constant space, which is the optimal complexity for this problem.

Approach 1: Using HashMaps to Track First Occurrence

This approach involves using hashmaps (dictionaries in Python) to keep track of the first occurrence of each lowercase letter and whether an uppercase version of it has already been seen. If a lowercase letter is seen before its uppercase counterpart, it is counted as special.

def count_special_characters(word):
    seen = {}
    special_set = set()
    for i, c in enumerate(word):
        if c.islower():
            if c not in seen:
                seen[c] = i
        elif c.isupper():
            lower = c.lower()
            if lower in seen and lower not in special_set and seen[lower] < i:
                special_set.add(lower)
    return len(special_set)
import java.util.*;

public class SpecialCharacters {
    public static int countSpecialCharacters(String word) {
        Map<Character, Integer> firstLowerIndex = new HashMap<>();
        Set<Character> specialSet = new HashSet<>();

        for (int i = 0; i < word.length(); i++) {
            char c = word.charAt(i);
            if (Character.isLowerCase(c)) {
                firstLowerIndex.putIfAbsent(c, i);
            } else if (Character.isUpperCase(c)) {
                char lower = Character.toLowerCase(c);
                if (firstLowerIndex.containsKey(lower) && firstLowerIndex.get(lower) < i && !specialSet.contains(lower)) {
                    specialSet.add(lower);
                }
            }
        }
        return specialSet.size();
    }
}
function countSpecialCharacters(word) {
    let firstLowerIndex = {};
    let specialSet = new Set();

    for (let i = 0; i < word.length; i++) {
        let c = word[i];
        if (c === c.toLowerCase()) {
            if (!(c in firstLowerIndex)) {
                firstLowerIndex[c] = i;
            }
        } else {
            let lower = c.toLowerCase();
            if (lower in firstLowerIndex && firstLowerIndex[lower] < i && !specialSet.has(lower)) {
                specialSet.add(lower);
            }
        }
    }
    return specialSet.size;
}

The function iterates through the string and records the first index of each lowercase letter seen. When an uppercase letter is found, it checks if the corresponding lowercase letter has been encountered before and if all its occurrences appear before this uppercase letter. A set is used to collect special letters only once.

Complexity

Time Complexity: O(n), where n is the length of the word. Space Complexity: O(n) for the hashmap and set underlying the implementation.

Try this approach in the editor

Approach 2: Two-Pass Array Approach

This approach entails two passes: the first to record the last occurrence of each letter (both lower and uppercase) and the second to determine if the lowercase occurs before its uppercase counterpart.

#include <iostream>
#include <vector>
#include <unordered_set>

int countSpecialCharacters(std::string word) {
    std::vector<int> lastLower(26, -1);
    std::vector<int> lastUpper(26, -1);
    std::unordered_set<char> specialSet;

    for (int i = 0; i < word.length(); i++) {
        char c = word[i];
        if (islower(c))
            lastLower[c - 'a'] = i;
        else
            lastUpper[c - 'A'] = i;
    }

    for (int i = 0; i < 26; i++) {
        if (lastLower[i] != -1 && lastUpper[i] != -1 && lastLower[i] < lastUpper[i]) {
            specialSet.insert('a' + i);
        }
    }
    return specialSet.size();
}
#include <stdio.h>
#include <stdbool.h>

int countSpecialCharacters(const char* word) {
    int last_index[52];
    for (int i = 0; i < 52; i++) last_index[i] = -1;
    int count = 0;
    bool found_special[26] = { false };

    for (int i = 0; word[i] != '\0'; i++) {
        char c = word[i];
        int idx = (c >= 'a') ? c - 'a' : c - 'A' + 26;
        last_index[idx] = i;
    }

    for (int i = 0; i < 26; i++) {
        int lower_idx = last_index[i];
        int upper_idx = last_index[i + 26];
        if (lower_idx != -1 && upper_idx != -1 && lower_idx < upper_idx) {
            found_special[i] = true;
            count++;
        }
    }
    return count;
}
using System;
using System.Collections.Generic;

public class SpecialCharacterCounter {
    public static int CountSpecialCharacters(string word) {
        int[] lastLower = new int[26];
        int[] lastUpper = new int[26];
        Array.Fill(lastLower, -1);
        Array.Fill(lastUpper, -1);
        HashSet<char> specialSet = new HashSet<char>();

        for (int i = 0; i < word.Length; i++) {
            char c = word[i];
            if (char.IsLower(c)) {
                lastLower[c - 'a'] = i;
            } else {
                lastUpper[c - 'A'] = i;
            }
        }

        for (int i = 0; i < 26; i++) {
            if (lastLower[i] != -1 && lastUpper[i] != -1 && lastLower[i] < lastUpper[i]) {
                specialSet.Add((char)('a' + i));
            }
        }
        return specialSet.Count;
    }
}

The C++ solution uses vectors to track last seen indices and an unordered_set for storing special characters. It ensures lowercase occurrences appear before uppercase ones.

Complexity

Time Complexity: O(n). Space Complexity: O(1).

Try this approach in the editor

Approach 3: Hash Table or Array

We define two hash tables or arrays first and last to store the positions where each letter first appears and last appears respectively.

Then we traverse the string word, updating first and last.

Finally, we traverse all lowercase and uppercase letters. If last[a] exists and first[b] exists and last[a] < first[b], it means that the letter a is a special letter, and we increment the answer by one.

The time complexity is O(n + |\Sigma|), and the space complexity is O(|\Sigma|). Where n is the length of the string word, and |\Sigma| is the size of the character set. In this problem, |\Sigma| leq 128.

function numberOfSpecialChars(word: string): number {
    const first: number[] = Array.from({ length: 'z'.charCodeAt(0) + 1 }, () => 0);
    const last: number[] = Array.from({ length: 'z'.charCodeAt(0) + 1 }, () => 0);
    for (let i = 0; i < word.length; ++i) {
        const j = word.charCodeAt(i);
        if (first[j] === 0) {
            first[j] = i + 1;
        }
        last[j] = i + 1;
    }
    let ans: number = 0;
    for (let i = 0; i < 26; ++i) {
        if (
            last['a'.charCodeAt(0) + i] &&
            first['A'.charCodeAt(0) + i] &&
            last['a'.charCodeAt(0) + i] < first['A'.charCodeAt(0) + i]
        ) {
            ++ans;
        }
    }
    return ans;
}
func numberOfSpecialChars(word string) (ans int) {
	first := make([]int, 'z'+1)
	last := make([]int, 'z'+1)
	for i, c := range word {
		if first[c] == 0 {
			first[c] = i + 1
		}
		last[c] = i + 1
	}
	for i := 0; i < 26; i++ {
		if last['a'+i] > 0 && first['A'+i] > 0 && last['a'+i] < first['A'+i] {
			ans++
		}
	}
	return
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Using HashMaps to Track First Occurrence

Time Complexity: O(n), where n is the length of the word. Space Complexity: O(n) for the hashmap and set underlying the implementation.

Two-Pass Array Approach

Time Complexity: O(n). Space Complexity: O(1).

Hash Table or Array–

Complexity analysis

ApproachTimeSpaceWhen to Use
HashMaps to Track First/Last OccurrenceO(n)O(1)General approach when using hash tables for character tracking in high-level languages
Two-Pass Array ApproachO(n)O(1)Preferred when working with fixed alphabets and aiming for faster constant factors

Frequently asked questions

Is Count the Number of Special Characters II easy or hard?

The problem is classified as Medium difficulty. The main challenge is recognizing the ordering constraint between lowercase and uppercase occurrences and storing positions efficiently so the validation step can be done in constant time per character.

Count the Number of Special Characters II Python/Java solution

Python and Java implementations commonly use dictionaries or arrays to record the first uppercase and last lowercase positions. After scanning the string once, a loop over the alphabet counts valid characters. Both implementations achieve O(n) time and O(1) space complexity.

How to solve Count the Number of Special Characters II in O(n)?

Scan the string and store two values for each letter: the last index of its lowercase form and the first index of its uppercase form. After the scan, iterate over all 26 characters and count those where both exist and the lowercase index is smaller than the uppercase index. This ensures all lowercase occurrences appear before the first uppercase occurrence.

What is the best approach for Count the Number of Special Characters II?

The best approach runs in O(n) time by recording the last index of each lowercase letter and the first index of each uppercase letter. After scanning the string once, check whether the last lowercase index occurs before the first uppercase index for each character. This guarantees the required ordering while keeping space usage constant.

Is Count the Number of Special Characters II asked at Google/Amazon/Meta?

Problems involving character tracking, case comparisons, and hash table lookups frequently appear in interviews at companies like Amazon, Google, and Meta. This problem tests string traversal, indexing logic, and efficient use of constant-sized data structures, which are common interview patterns.

What data structure is used in Count the Number of Special Characters II?

The solution typically uses a hash table or fixed-size arrays to store character positions. Hash maps provide flexible key lookups, while arrays of size 26 offer faster indexing because the alphabet size is constant.

What is the time complexity of Count the Number of Special Characters II?

The optimal solution runs in O(n) time where n is the length of the string. Each character is processed once to record its position, and then a constant loop over 26 letters verifies the conditions. Space complexity remains O(1) because only fixed-size arrays or maps for the alphabet are used.

Comments

Now write it yourselfClose this page and solve Count the Number of Special Characters II in the editor, without looking.
Practise Count the Number of Special Characters II