Reconstruct Original Digits from English
MedPrompt
Given a string s containing an out-of-order English representation of digits 0-9, return the digits in ascending order.
Example 1:
Input: s = "owoztneoer"
Output: "012"Example 2:
Input: s = "fviefuro"
Output: "45"
Constraints:
1 <= s.length <= 105s[i]is one of the characters["e","g","f","i","h","o","n","s","r","u","t","w","v","x","z"].sis guaranteed to be valid.
Approaches
2 approaches with complexity analysis and trade-offs.
This approach frames the problem as finding the correct count for each digit (0-9) that accounts for all characters in the input string. It uses a recursive backtracking algorithm to explore all possible combinations of digit counts.
Algorithm
- Create a frequency map
charCountsfor the characters ins. - Create an array
digitCountsof size 10 to store the result. - Define a recursive function
backtrack(digit, currentCounts):- Base Case: If
digit == 10, check if all values incurrentCountsare 0. If yes, a solution is found, returntrue; otherwise, returnfalse. - Determine the word for the current
digit. - Calculate the maximum possible number of times (
maxCount) this word can be formed fromcurrentCounts. - Loop
ifrom 0 tomaxCount:- Set
digitCounts[digit] = i. - Create
nextCountsby subtracting characters foricopies of the word fromcurrentCounts. - If
backtrack(digit + 1, nextCounts)returnstrue, then a solution is found down this path, so returntrue.
- Set
- If the loop completes, no solution was found for this branch. Return
false.
- Base Case: If
- Initiate the process with
backtrack(0, charCounts). - If it returns
true, build the result string fromdigitCountsby appending each digit the required number of times in ascending order.
Walkthrough
First, we count the frequency of each character in the input string s. We then define a recursive function, say backtrack(digit, counts), which tries to determine the number of occurrences for the current digit. The function iterates through all possible counts for the current digit, from 0 up to the maximum possible (limited by the available characters in counts). For each possible count, it subtracts the corresponding characters from the counts map and makes a recursive call for the next digit (digit + 1). If a recursive call returns true (meaning a valid combination was found for the subsequent digits), it means we've found a solution. We store the count for the current digit and also return true. The base case for the recursion is when we have considered all digits (i.e., digit == 10). At this point, if all character counts are zero, we have successfully reconstructed the original digits. Once the backtracking process successfully finds the counts for all digits, we construct the final string.
class Solution { // Word representations for digits 0-9 String[] words = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"}; // Character counts for each word int[][] wordCharCounts = new int[10][26]; // Resulting digit counts int[] digitCounts = new int[10]; public String originalDigits(String s) { // Pre-calculate character counts for each digit word for (int i = 0; i < 10; i++) { for (char c : words[i].toCharArray()) { wordCharCounts[i][c - 'a']++; } } // Count characters in the input string int[] sCounts = new int[26]; for (char c : s.toCharArray()) { sCounts[c - 'a']++; } // Start backtracking from digit 0 if (backtrack(0, sCounts)) { StringBuilder result = new StringBuilder(); for (int i = 0; i < 10; i++) { for (int j = 0; j < digitCounts[i]; j++) { result.append(i); } } return result.toString(); } return ""; // Should not happen based on problem constraints } private boolean backtrack(int digit, int[] currentCounts) { if (digit == 10) { // Base case: check if all characters have been used for (int count : currentCounts) { if (count != 0) { return false; } } return true; } // Determine max possible count for the current digit's word int maxCount = Integer.MAX_VALUE; for (int i = 0; i < 26; i++) { if (wordCharCounts[digit][i] > 0) { maxCount = Math.min(maxCount, currentCounts[i] / wordCharCounts[digit][i]); } } // Iterate through all possible counts for the current digit for (int i = 0; i <= maxCount; i++) { int[] nextCounts = new int[26]; System.arraycopy(currentCounts, 0, nextCounts, 0, 26); for (int j = 0; j < 26; j++) { nextCounts[j] -= i * wordCharCounts[digit][j]; } digitCounts[digit] = i; if (backtrack(digit + 1, nextCounts)) { return true; } } return false; }}Complexity
Time
O(K^10 * L) where K is the maximum possible count for any single digit, and L is the alphabet size (26). The recursion depth is 10, and at each level, we can branch up to K times. This is exponential and too slow for the given constraints.
Space
O(1). The recursion depth is constant (10), and at each level, we store a character count array of constant size (26).
Trade-offs
Pros
It's a general approach that could work for similar problems where a direct counting trick isn't obvious.
Cons
Extremely inefficient due to its exponential time complexity.
Will result in a 'Time Limit Exceeded' (TLE) error for the given constraints.
More complex to implement correctly compared to the optimal solution.
Solutions
Solution
class Solution { public String originalDigits ( String s ) { int [] counter = new int [ 26 ]; for ( char c : s . toCharArray ()) { ++ counter [ c - 'a' ]; } int [] cnt = new int [ 10 ]; cnt [ 0 ] = counter [ 'z' - 'a' ]; cnt [ 2 ] = counter [ 'w' - 'a' ]; cnt [ 4 ] = counter [ 'u' - 'a' ]; cnt [ 6 ] = counter [ 'x' - 'a' ]; cnt [ 8 ] = counter [ 'g' - 'a' ]; cnt [ 3 ] = counter [ 'h' - 'a' ] - cnt [ 8 ]; cnt [ 5 ] = counter [ 'f' - 'a' ] - cnt [ 4 ]; cnt [ 7 ] = counter [ 's' - 'a' ] - cnt [ 6 ]; cnt [ 1 ] = counter [ 'o' - 'a' ] - cnt [ 0 ] - cnt [ 2 ] - cnt [ 4 ]; cnt [ 9 ] = counter [ 'i' - 'a' ] - cnt [ 5 ] - cnt [ 6 ] - cnt [ 8 ]; StringBuilder sb = new StringBuilder (); for ( int i = 0 ; i < 10 ; ++ i ) { for ( int j = 0 ; j < cnt [ i ]; ++ j ) { sb . append ( i ); } } return sb . toString (); } }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.