Mutating counts without cleanup
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Move from brute-force thinking to an efficient approach using hash map strategy.
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 * 105word consists of only lowercase and uppercase English letters.Problem summary: 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.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map
"aaAbcBC"
"abc"
"AbBCab"
detect-capital)greatest-english-letter-in-upper-and-lower-case)count-the-number-of-special-characters-i)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #3121: Count the Number of Special Characters II
class Solution {
public int numberOfSpecialChars(String word) {
int[] first = new int['z' + 1];
int[] last = new int['z' + 1];
for (int i = 1; i <= word.length(); ++i) {
int j = word.charAt(i - 1);
if (first[j] == 0) {
first[j] = i;
}
last[j] = i;
}
int ans = 0;
for (int i = 0; i < 26; ++i) {
if (last['a' + i] > 0 && first['A' + i] > 0 && last['a' + i] < first['A' + i]) {
++ans;
}
}
return ans;
}
}
// Accepted solution for LeetCode #3121: Count the Number of Special Characters II
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
}
# Accepted solution for LeetCode #3121: Count the Number of Special Characters II
class Solution:
def numberOfSpecialChars(self, word: str) -> int:
first, last = {}, {}
for i, c in enumerate(word):
if c not in first:
first[c] = i
last[c] = i
return sum(
a in last and b in first and last[a] < first[b]
for a, b in zip(ascii_lowercase, ascii_uppercase)
)
// Accepted solution for LeetCode #3121: Count the Number of Special Characters II
// Rust example auto-generated from java reference.
// Replace the signature and local types with the exact LeetCode harness for this problem.
impl Solution {
pub fn rust_example() {
// Port the logic from the reference block below.
}
}
// Reference (java):
// // Accepted solution for LeetCode #3121: Count the Number of Special Characters II
// class Solution {
// public int numberOfSpecialChars(String word) {
// int[] first = new int['z' + 1];
// int[] last = new int['z' + 1];
// for (int i = 1; i <= word.length(); ++i) {
// int j = word.charAt(i - 1);
// if (first[j] == 0) {
// first[j] = i;
// }
// last[j] = i;
// }
// int ans = 0;
// for (int i = 0; i < 26; ++i) {
// if (last['a' + i] > 0 && first['A' + i] > 0 && last['a' + i] < first['A' + i]) {
// ++ans;
// }
// }
// return ans;
// }
// }
// Accepted solution for LeetCode #3121: Count the Number of Special Characters II
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;
}
Use this to step through a reusable interview workflow for this problem.
For each element, scan the rest of the array looking for a match. Two nested loops give n × (n−1)/2 comparisons = O(n²). No extra space since we only use loop indices.
One pass through the input, performing O(1) hash map lookups and insertions at each step. The hash map may store up to n entries in the worst case. This is the classic space-for-time tradeoff: O(n) extra memory eliminates an inner loop.
Review these before coding to avoid predictable interview regressions.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.