You are given a string s
that contains a jumbled concatenation of the English words for digits zero through nine (e.g., "zero", "one", ..., "nine"), possibly repeated and in any order. Your task is to reconstruct and return the original digits in ascending order as a string.
s
belongs to exactly one digit word.
Example:
Input: s = "owoztneoer"
Output: "012"
At first glance, the problem seems to require finding all possible combinations of digit words that could form the input string. A brute-force approach would try every possible combination of digit words and check if their concatenation matches s
. However, this would be extremely inefficient due to the exponential number of possibilities.
Looking deeper, we notice that certain letters only appear in specific digit words. For example, the letter 'z' only appears in "zero", and 'w' only in "two". These unique letters can serve as anchors to identify the presence and count of those digits directly. Once we account for digits with unique letters, we can use a process of elimination to deduce the remaining digits.
The key is to count the frequency of each letter, use unique letters to identify some digits, and adjust the counts accordingly for overlapping letters in other digit words.
We solve the problem by leveraging the unique letters in certain digit words and systematically reducing the letter counts. Here's a step-by-step breakdown:
s
. This allows O(1) lookups and updates.This approach ensures that each letter is only used once, and all digits are accounted for efficiently.
Let's walk through the example input s = "owoztneoer"
:
Brute-force:
s
.
s
.
The solution leverages the unique occurrence of certain letters in digit words to efficiently reconstruct the original digits. By counting letters and systematically removing identified digits, we avoid brute-force and achieve a linear-time solution. The approach is elegant because it uses the structure of the English language itself, turning what seems like a permutation problem into a simple counting and deduction exercise.
from collections import Counter
class Solution:
def originalDigits(self, s: str) -> str:
count = Counter(s)
out = [0] * 10
# Unique letters for each digit
out[0] = count['z']
out[2] = count['w']
out[4] = count['u']
out[6] = count['x']
out[8] = count['g']
# For non-unique, subtract those already counted
out[1] = count['o'] - out[0] - out[2] - out[4]
out[3] = count['h'] - out[8]
out[5] = count['f'] - out[4]
out[7] = count['s'] - out[6]
out[9] = count['i'] - out[5] - out[6] - out[8]
result = []
for i in range(10):
result.append(str(i) * out[i])
return ''.join(result)
#include <string>
#include <vector>
#include <unordered_map>
using namespace std;
class Solution {
public:
string originalDigits(string s) {
vector<int> count(26, 0);
for (char c : s) count[c - 'a']++;
vector<int> out(10, 0);
out[0] = count['z' - 'a'];
out[2] = count['w' - 'a'];
out[4] = count['u' - 'a'];
out[6] = count['x' - 'a'];
out[8] = count['g' - 'a'];
out[1] = count['o' - 'a'] - out[0] - out[2] - out[4];
out[3] = count['h' - 'a'] - out[8];
out[5] = count['f' - 'a'] - out[4];
out[7] = count['s' - 'a'] - out[6];
out[9] = count['i' - 'a'] - out[5] - out[6] - out[8];
string result;
for (int i = 0; i <= 9; ++i) {
result += string(out[i], '0' + i);
}
return result;
}
};
class Solution {
public String originalDigits(String s) {
int[] count = new int[26];
for (char c : s.toCharArray()) count[c - 'a']++;
int[] out = new int[10];
out[0] = count['z' - 'a'];
out[2] = count['w' - 'a'];
out[4] = count['u' - 'a'];
out[6] = count['x' - 'a'];
out[8] = count['g' - 'a'];
out[1] = count['o' - 'a'] - out[0] - out[2] - out[4];
out[3] = count['h' - 'a'] - out[8];
out[5] = count['f' - 'a'] - out[4];
out[7] = count['s' - 'a'] - out[6];
out[9] = count['i' - 'a'] - out[5] - out[6] - out[8];
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
for (int j = 0; j < out[i]; j++) {
sb.append(i);
}
}
return sb.toString();
}
}
var originalDigits = function(s) {
const count = {};
for (let c of s) count[c] = (count[c] || 0) + 1;
const out = Array(10).fill(0);
out[0] = count['z'] || 0;
out[2] = count['w'] || 0;
out[4] = count['u'] || 0;
out[6] = count['x'] || 0;
out[8] = count['g'] || 0;
out[1] = (count['o'] || 0) - out[0] - out[2] - out[4];
out[3] = (count['h'] || 0) - out[8];
out[5] = (count['f'] || 0) - out[4];
out[7] = (count['s'] || 0) - out[6];
out[9] = (count['i'] || 0) - out[5] - out[6] - out[8];
let result = '';
for (let i = 0; i < 10; i++) {
result += String(i).repeat(out[i]);
}
return result;
};