题目:首先将电话号码中的每个数字加上8取个位,然后使用对应的大写字母代替 ("ZERO", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE"), 然后随机打乱这些字母,所生成的字符串即为电话号码对应的分身。现给你一个电话号码的分身,求出分身前的最小电话号码(允许前导0)
输入
4
EIGHT
ZEROTWOONE
OHWETENRTEO
OHEWTIEGTHENRTEO
输出
0
234
345
0345
思路:依次解码具有独一无二字符的数字,具有这样特点的数字有五个分别是FOUR(U),SIX(X),TWO(W),EIGHT(G),ZERO(Z),可以根据独特字符的个数直接判断有多少个相应的数字,例如有3个U那么就一定有3个FOUR...,解码完成这五个数字之后另外的数字也会由于这些数字的移除而具有了独一无二的字符。【来源牛客网:https://www.nowcoder.com/questionTerminal/493d71a992f44554a500ed818056e1a6】
代码一(用几个数组分别作为桶,存储字母或数字的出现次数)
#include<iostream>
#include<string>
#include<vector>
#include<memory>
using namespace std;
int alph[26]; //字符串中每个字母出现的个数
int numCnt[10]; //字符串中每个数字出现的个数
string numWord[10] = { "ZERO","ONE","TWO","THREE","FOUR","FIVE","SIX","SEVEN","EIGHT","NINE" };
//解码顺序和对应的关键字母
int keyNum[10] = { 0,2,4,6,8,1,7,9,5,3 };
char keyAlph[10] = { 'Z','W','U','X','G','O','S','N','V','T' };
//计算numCnt数组
void decode() {
for (int i = 0; i < 10;i++) {
while (alph[keyAlph[i] - 'A'] != 0) {
for (char j : numWord[keyNum[i]]) alph[j - 'A']--;
numCnt[keyNum[i]]++;
}
}
}
int main() {
int n;
while (cin >> n) {
string *strArr=new string[n];
for (int i = 0; i < n; i++) cin >> strArr[i];
for (int i = 0; i < n; i++) {
string str = strArr[i];
//one case
memset(numCnt, 0, 10 * sizeof(numCnt[0]));
memset(alph, 0, 26 * sizeof(alph[0]));
for (char j : str) alph[j - 'A']++;
decode();
for (int j = 0; j < 10; j++)
while (numCnt[(j + 8) % 10]-->0) cout << j;
cout << endl;
}
}
}
代码二(与代码差不多,区别是计数方式,用map存储各字母的次数,然后依次计算各数字的次数)
while (T--)
{
cin >> input;
map<char, size_t> help;
for (auto& t : input)
{
help[t] += 1;
}
vector<size_t> count(10);
count[0] = help['Z']; //ZERO
count[2] = help['W']; //TWO
count[4] = help['U']; //FOUR
count[1] = help['O'] - count[0] - count[2] - count[4]; //ONE
count[6] = help['X']; //SIX
count[8] = help['G']; //EIGHT
count[3] = help['T'] - count[2] - count[8]; //TRHEE
count[5] = help['F'] - count[4]; //FIVE
count[7] = help['V'] - count[5]; //SEVEN
count[9] = help['I'] - count[6] - count[5] - count[8]; //NINE //NINE
vector<size_t> numsBefore(10);
for (size_t i = 0; i<10; i++)
numsBefore[(i + 2) % 10] = count[i];//号码还原
for (size_t i = 0; i<10; i++)
{
for (int j = 0; j<numsBefore[i]; j++)
cout << i;
}
cout << endl;
}
注意打印输出这部分代码,下标直接用加8取余来表示
for (int j = 0; j < 10; j++)
while (numCnt[(j + 8) % 10]-->0) cout << j;
我之前的蹩脚写法:
for (int j = 0, k = 8; j < 10; j++, k = j + 8) {
if (j + 8 >= 10) k = j - 2;
while (numCnt[k] > 0) {
cout << j;
numCnt[k]--;
}
}