3581. Count Odd Letters from Number 🔒
Problem Description
You are given an integer n
and need to perform the following steps:
- Convert each digit of
n
into its lowercase English word (for example, 4 → "four", 1 → "one"). - Concatenate those words in the original digit order to form a string
s
.
Return the number of distinct characters in s
that appear an odd number of times.
Intuition
We want to find out which characters appear an odd number of times after translating each digit of n
into its English word. Instead of counting each letter directly, we can track the oddness or evenness of their appearances using a bitmask. Every time a character appears, we flip its bit in a binary number, so after finishing, each bit set to 1 stands for a character that appeared an odd number of times. This way, we save space and quickly find the answer by counting the number of 1s in the final bitmask.
Solution Approach
We use simulation and bit manipulation to solve the problem efficiently.
First, create a mapping from digits 0
to 9
to their corresponding English words using a dictionary.
Then, for the given integer n
, process each digit:
- For each digit, look up its English word and iterate through each character in that word.
- For each character, use a bitmask (an integer variable called
mask
) to track its occurrence parity (odd/even). Assign each character a unique bit position by computingord(c) - ord("a")
for lowercase English letters. - Flipping the bit with the XOR operation every time the character is encountered means that at the end, each bit set to
1
inmask
represents a character that appears an odd number of times.
After processing all digits and their word forms, count the number of set bits (1
s) in the final bitmask using mask.bit_count()
. This gives the answer: the number of distinct characters with an odd count.
The core steps are:
- Loop through digits of
n
(from least to most significant). - For each digit, iterate over its letter representation.
- Flip the bitmask for each letter.
- Return the total count of bits set to
1
in the bitmask.
This approach leverages constant alphabet size (since there are only 26 lowercase English letters), making the solution fast and space-efficient.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with n = 104
.
-
Convert digits to words
- 1 → "one"
- 0 → "zero"
- 4 → "four"
- Concatenate:
"onezerofour"
-
Track character occurrences and parity
-
Processing characters one by one and tracking their parity with a bitmask (mapping 'a' to position 0, 'b' to 1, ..., 'z' to 25):
-
"o" (from "one"): appears (mask flips at position of 'o')
-
"n": appears
-
"e": appears
-
"z": appears
-
"e": appears again (mask flips: second appearance is even, so back to 0)
-
"r": appears
-
"o": appears again (mask flips back to 0 for 'o')
-
"f": appears
-
"o": appears (third time, mask flips back to 1)
-
"u": appears
-
"r": appears again (mask flips back to 0 for 'r')
After processing all characters, the final characters with odd occurrence counts are:
- "n", "z", "f", "o", "u"
-
-
Count set bits in the bitmask
- The answer is 5 because these characters appear an odd number of times.
Summary in the context of the solution:
- For
n = 104
, form"onezerofour"
, track odd/even letter counts with a bitmask, and find that 5 distinct characters ("n", "z", "f", "o", "u") appear an odd number of times.
Solution Implementation
1# Mapping of digits to their English word representations.
2digit_to_word = {
3 0: "zero",
4 1: "one",
5 2: "two",
6 3: "three",
7 4: "four",
8 5: "five",
9 6: "six",
10 7: "seven",
11 8: "eight",
12 9: "nine",
13}
14
15class Solution:
16 def countOddLetters(self, n: int) -> int:
17 # Initialize mask to represent parity of letter counts.
18 mask = 0
19 # Process each digit of the number 'n'.
20 while n:
21 digit = n % 10 # Extract the last digit.
22 n //= 10 # Remove the last digit.
23 # For each letter in the English representation of the digit,
24 # toggle (XOR) its corresponding bit in 'mask'.
25 for char in digit_to_word[digit]:
26 mask ^= 1 << (ord(char) - ord("a"))
27 # Count how many letters appear an odd number of times
28 # by counting the number of set bits in 'mask'.
29 return mask.bit_count()
30
1class Solution {
2 // Static map to store the English spelling of single digit numbers (0-9)
3 private static final Map<Integer, String> digitToWord = new HashMap<>();
4 static {
5 digitToWord.put(0, "zero");
6 digitToWord.put(1, "one");
7 digitToWord.put(2, "two");
8 digitToWord.put(3, "three");
9 digitToWord.put(4, "four");
10 digitToWord.put(5, "five");
11 digitToWord.put(6, "six");
12 digitToWord.put(7, "seven");
13 digitToWord.put(8, "eight");
14 digitToWord.put(9, "nine");
15 }
16
17 /**
18 * Returns the count of distinct letters that appear an odd number of times
19 * in the English words for the digits of n.
20 *
21 * @param n The input number
22 * @return The number of letters with odd frequency
23 */
24 public int countOddLetters(int n) {
25 // Bitmask to track parity of each letter (a-z) using bit manipulation
26 int mask = 0;
27 while (n > 0) {
28 int digit = n % 10;
29 n /= 10;
30 // Get the English word for this digit
31 String word = digitToWord.get(digit);
32 // Flip the corresponding bit for each letter
33 for (char ch : word.toCharArray()) {
34 mask ^= 1 << (ch - 'a');
35 }
36 }
37 // The number of bits set represents the number of letters that appeared odd times
38 return Integer.bitCount(mask);
39 }
40}
41
1#include <unordered_map>
2#include <string>
3
4class Solution {
5public:
6 int countOddLetters(int n) {
7 // Map digits to their English word representations
8 static const std::unordered_map<int, std::string> digitToWord = {
9 {0, "zero"},
10 {1, "one"},
11 {2, "two"},
12 {3, "three"},
13 {4, "four"},
14 {5, "five"},
15 {6, "six"},
16 {7, "seven"},
17 {8, "eight"},
18 {9, "nine"}
19 };
20
21 int letterMask = 0; // Bitmask to track odd/even counts of each letter
22
23 // Process each digit of the number
24 while (n > 0) {
25 int digit = n % 10; // Get the last digit
26 n /= 10; // Remove the last digit
27
28 // For each character in the word for this digit
29 for (char ch : digitToWord.at(digit)) {
30 // Use XOR to toggle the bit representing this letter
31 letterMask ^= 1 << (ch - 'a');
32 }
33 }
34
35 // Count the number of set bits (letters with odd occurrences)
36 return __builtin_popcount(letterMask);
37 }
38};
39
1// Mapping from digit to its English word representation
2const digitToWord: Record<number, string> = {
3 0: 'zero',
4 1: 'one',
5 2: 'two',
6 3: 'three',
7 4: 'four',
8 5: 'five',
9 6: 'six',
10 7: 'seven',
11 8: 'eight',
12 9: 'nine',
13};
14
15/**
16 * For a given number n, convert each digit to its English word,
17 * and for all letters, count the number of letters that occur an odd number of times.
18 * Uses bitmasking to efficiently track letter parity.
19 */
20function countOddLetters(n: number): number {
21 let mask = 0;
22 while (n > 0) {
23 const digit = n % 10;
24 n = Math.floor(n / 10);
25
26 // For each letter in the word for this digit, toggle its bit
27 for (const ch of digitToWord[digit]) {
28 const bit = ch.charCodeAt(0) - 'a'.charCodeAt(0);
29 mask ^= 1 << bit;
30 }
31 }
32
33 // Count number of bits set in mask (number of odd-occurrence letters)
34 return bitCount(mask);
35}
36
37/**
38 * Counts the number of set bits (1s) in the binary representation of i.
39 * Uses parallel bit counting technique (Hamming Weight).
40 */
41function bitCount(i: number): number {
42 i = i - ((i >>> 1) & 0x55555555); // Subtract each pair of bits
43 i = (i & 0x33333333) + ((i >>> 2) & 0x33333333); // Sum bits in each nibble
44 i = (i + (i >>> 4)) & 0x0f0f0f0f; // Sum bits in each byte
45 i = i + (i >>> 8); // Aggregate higher
46 i = i + (i >>> 16); // Aggregate final result
47 return i & 0x3f; // Only the lowest 6 bits are needed (26 letters)
48}
49
Time and Space Complexity
-
Time Complexity: The code processes each digit of
n
, so the number of iterations is proportional to the number of digits, which isO(\log_{10} n)
. For each digit (from 0 to 9), it loops over a fixed number of characters in the corresponding word representation; since the length of these strings is constant and does not depend onn
, it can be treated asO(1)
per digit. Therefore, the overall time complexity isO(\log n)
. -
Space Complexity: The only extra space used is a single integer variable
mask
, regardless of the input size. The dictionaryd
has a fixed size and does not scale with input. Thus, the space complexity isO(1)
.
Problem: Given a list of tasks and a list of requirements, compute a sequence of tasks that can be performed, such that we complete every task once while satisfying all the requirements.
Which of the following method should we use to solve this problem?
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!