Number of Different Integers in a String
EasyPrompt
You are given a string word that consists of digits and lowercase English letters.
You will replace every non-digit character with a space. For example, "a123bc34d8ef34" will become " 123 34 8 34". Notice that you are left with some integers that are separated by at least one space: "123", "34", "8", and "34".
Return the number of different integers after performing the replacement operations on word.
Two integers are considered different if their decimal representations without any leading zeros are different.
Example 1:
Input: word = "a123bc34d8ef34"
Output: 3
Explanation: The three different integers are "123", "34", and "8". Notice that "34" is only counted once.Example 2:
Input: word = "leet1234code234"
Output: 2Example 3:
Input: word = "a1b01c001"
Output: 1
Explanation: The three integers "1", "01", and "001" all represent the same integer because
the leading zeros are ignored when comparing their decimal values.
Constraints:
1 <= word.length <= 1000wordconsists of digits and lowercase English letters.
Approaches
2 approaches with complexity analysis and trade-offs.
This approach leverages built-in string manipulation functions for a straightforward implementation. First, we use a regular expression to replace all non-digit characters with spaces. This effectively isolates the numbers within the string. Then, we split the resulting string by these spaces to obtain an array of individual number strings. Finally, we iterate through these strings, normalize them by removing any leading zeros, and add them to a HashSet. The set's nature of storing only unique elements allows us to easily find our answer by returning its final size.
Algorithm
- Initialize a
HashSet<String>to store unique numbers. - Use a regular expression like
[a-z]to replace all lowercase letters in the inputwordwith a space. This results in a new string where numbers are separated by spaces. - Trim any leading or trailing whitespace from the modified string to handle edge cases.
- Split the string by one or more whitespace characters (
"\\s+") to get an array of strings. Each element in this array is a number represented as a string. - Iterate through this array of number strings.
- For each non-empty string, normalize it by removing any leading zeros. For example,
"01"and"001"both become"1". A string of only zeros, like"00", becomes"0". - Add the normalized string to the
HashSet. The set automatically handles duplicates. - Finally, the number of different integers is the size of the
HashSet.
Walkthrough
The core idea is to transform the input string into a format that is easy to parse. By replacing all letters with spaces, we get a string like " 123 34 8 34". Splitting this by whitespace gives us the number candidates: ["123", "34", "8", "34"]. The next crucial step is normalization. Since "01" and "1" represent the same integer, we must convert them to a canonical form before storing them. A simple way to do this is to remove all leading zeros. After normalizing each string, we add it to a HashSet. The set ensures that even though "34" appears twice, it's only stored once. The final count is simply the number of elements in the set.
import java.util.HashSet;import java.util.Set; class Solution { public int numDifferentIntegers(String word) { // 1. Replace all non-digits with spaces. String processedWord = word.replaceAll("[a-z]", " "); // 2. Trim and split by one or more spaces. String[] numberStrings = processedWord.trim().split("\\s+"); Set<String> uniqueIntegers = new HashSet<>(); // Handle case where the string has no numbers. if (processedWord.trim().isEmpty()) { return 0; } // 3. Iterate, normalize, and add to set. for (String numStr : numberStrings) { // Find the first non-zero character to remove leading zeros. int i = 0; while (i < numStr.length() - 1 && numStr.charAt(i) == '0') { i++; } uniqueIntegers.add(numStr.substring(i)); } // 4. Return the size of the set. return uniqueIntegers.size(); }}Complexity
Time
O(N), where N is the length of the input string `word`. The `replaceAll`, `trim`, and `split` operations each take time proportional to the string length. The subsequent loop to process and store the numbers also takes O(N) in total, as the sum of the lengths of all number strings is at most N.
Space
O(N), where N is the length of the input string `word`. This space is used for the new string created by `replaceAll`, the array of strings from `split`, and the `HashSet`. In the worst case, all of these can be proportional to the input size.
Trade-offs
Pros
Conceptually simple and easy to implement using standard library functions.
The code is often more concise and readable for those familiar with regular expressions.
Cons
Can be less efficient due to the overhead of regular expression processing.
Creates several intermediate data structures (a new string from
replaceAlland an array fromsplit), which can increase memory usage and have higher constant factors for time complexity.
A more optimized approach is to iterate through the string just once, character by character. We can use pointers or indices to identify numeric segments directly from the input string without creating large intermediate copies. As we find each number, we extract it, normalize it by removing leading zeros, and add the canonical form to a HashSet. This method avoids the overhead associated with regular expressions and creating intermediate data structures, making it more efficient in terms of both memory and speed.
Algorithm
- Initialize a
HashSet<String>to store the unique normalized integers. - Initialize a pointer
i = 0to traverse the stringwordfrom left to right. - Loop while
iis less than the length ofword:- If the character at
iis a letter, it's a separator. Simply incrementiand continue to the next character. - If the character at
iis a digit, it marks the beginning of a number.- Use a second pointer
j, starting fromi, to find the end of the contiguous block of digits. Keep incrementingjas long as it's within bounds and points to a digit. - The substring from
itoj-1is our number string. - To handle leading zeros, find the index of the first non-zero digit in this substring. Let's call this index
start. - The normalized number is the substring from
starttoj. - Add this normalized string to the
HashSet. - Crucially, update the main pointer
itojto continue scanning from the character immediately after the number we just processed.
- Use a second pointer
- If the character at
- Return the final size of the
HashSet.
Walkthrough
This approach manually parses the string. We iterate with a primary pointer i. When word.charAt(i) is a digit, we know we've started a number. We then use a secondary pointer j to find where this sequence of digits ends. The substring word.substring(i, j) gives us the number. We then perform normalization in-place on these indices. We advance a start pointer from i forward as long as we see leading zeros (while ensuring we don't consume the entire number if it's just "0"). The substring from start to j is the canonical representation, which we add to our set. After processing a number, we set i = j to avoid re-scanning the same digits and continue our single pass through the string.
import java.util.HashSet;import java.util.Set; class Solution { public int numDifferentIntegers(String word) { Set<String> uniqueIntegers = new HashSet<>(); int n = word.length(); int i = 0; while (i < n) { if (Character.isDigit(word.charAt(i))) { // Found the start of a number int j = i; // Find the end of the number segment while (j < n && Character.isDigit(word.charAt(j))) { j++; } // Find the start of the number after skipping leading zeros int start = i; while (start < j - 1 && word.charAt(start) == '0') { start++; } // Add the normalized number string to the set uniqueIntegers.add(word.substring(start, j)); // Continue scanning from the end of the found number i = j; } else { // It's a letter, just move to the next character i++; } } return uniqueIntegers.size(); }}Complexity
Time
O(N), where N is the length of the input string `word`. We iterate through the string with the main pointer `i`. The inner loops also advance pointers (`j`, `start`) over segments of the string. Each character of the string is visited only a constant number of times. The total time for all substring operations and set insertions is O(N).
Space
O(N), where N is the length of the input string. The space is dominated by the `HashSet`. In the worst-case scenario (e.g., '1a2a3a...'), the set could store O(N) distinct strings, with a total character count proportional to N.
Trade-offs
Pros
More efficient in terms of both time and space as it avoids creating large intermediate data structures like new strings and arrays.
Processes the string in a single pass, leading to better performance with lower constant factors, especially for large inputs.
Cons
The implementation is slightly more complex, requiring manual pointer management to identify and process numbers.
The code might be less immediately obvious to read compared to the high-level regex-based solution.
Solutions
Solution
class Solution {public int numDifferentIntegers(String word) { Set<String> s = new HashSet<>(); int n = word.length(); for (int i = 0; i < n; ++i) { if (Character.isDigit(word.charAt(i))) { while (i < n && word.charAt(i) == '0') { ++i; } int j = i; while (j < n && Character.isDigit(word.charAt(j))) { ++j; } s.add(word.substring(i, j)); i = j; } } return s.size(); }}class Solution {public: int numDifferentIntegers(string word) { unordered_set<string> s; int n = word.size(); for (int i = 0; i < n; ++i) { if (isdigit(word[i])) { while (i < n && word[i] == '0') ++i; int j = i; while (j < n && isdigit(word[j])) ++j; s.insert(word.substr(i, j - i)); i = j; } } return s.size(); }};class Solution: def numDifferentIntegers(self, word: str) -> int: s = set() i, n = 0, len(word) while i < n: if word[i]. isdigit(): while i < n and word[i] == '0': i += 1 j = i while j < n and word[j]. isdigit(): j += 1 s . add(word[i: j]) i = j i += 1 return len(s)Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.