Problem statement could be found @https://leetcode.com/problems/reconstruct-original-digits-from-english/
Thought process -
The first approach that came to my mind was recursion + backtracking, but given the length of input string could go upto 50,000 there was a high possibility of the solution giving timeout.
Next I started thinking of unique properties of the number strings, there is realized there some unique characters in number like
1. x in six, x does not occur in any other number
2. w in two, w also does not occur in any other number
3. u in four, u doesn't occur in any other number
4. Similarly, z in zero & g in eight
So it is extremely easy to identify number like two,six, four, zero and eight. But what about other numbers? So, lets see what are the remaining numbers
one, three, five, seven, nine.
Lets check the uniqueness in above numbers
1. o in one
2. t in Three
3. s in Seven
4. f in Five
5. i in Nine
Hence, finding the count of o, t, s, f and i, we can get remaining characters.
Following is the code, the solution is accepted by Leetcode and runs in 26 msec for all testcases
class Solution {
map<char, string> uDict;
map<char, int> uMap;
map<char, string> sDict;
map<char, int> sMap;
int handled;
int toHandle ;
public:
void uDigit(){
uDict['z'] = "zero";
uDict['w'] = "two";
uDict['g'] = "eight";
uDict['u'] = "four";
uDict['x'] = "six";
uMap['z'] = 0;
uMap['w'] = 2;
uMap['g'] = 8;
uMap['u'] = 4;
uMap['x'] = 6;
}
void sDigit(){
sDict['t'] = "three";
sDict['o'] = "one";
sDict['s'] = "seven";
sDict['i'] = "nine";
sDict['f'] = "five";
sMap['t'] = 3;
sMap['o'] = 1;
sMap['s'] = 7;
sMap['i'] = 9;
sMap['f'] = 5;
}
bool rem(int arr[], int count, string str){
for (auto s=str.begin(); s != str.end();s++){
if ( arr[*s-'a'] < count )
return false;
}
for (auto s=str.begin(); s != str.end();s++){
arr[*s-'a'] = arr[*s-'a'] - count;
}
handled = handled+ str.size() * count;
return true;
}
void tryUMap(int arr[],int op[],
map<char, string> &dict, map<char, int> &numMap){
for (auto x = dict.begin(); x!= dict.end(); x++){
if (handled == toHandle)
return ;
if (arr[x->first-'a'] != 0){
int count = arr[x->first-'a'] ;
if ( rem(arr, count, x->second) == true){
op[numMap[x->first] ] = op[numMap[x->first] ] + count;
}
}
}
}
string originalDigits(string s) {
handled = 0;
uDigit();
sDigit();
int arr[26] = {0};
toHandle = s.size();
for (int i=0;i<s.size();i++){
arr[s.at(i) - 'a'] ++;
}
int op[10] = {0};
tryUMap(arr,op,uDict, uMap);
tryUMap(arr,op,sDict, sMap);
std::ostringstream oss;
string os="";
for (int i=0;i<10;i++){
while (op[i] != 0){
oss <<i;
op[i]--;
}
}
return oss.str();
}
};