WOHOOOO!!!
这个题目终于写出来了,用了好长时间,正好最近开学,写作业时候一起把这一题写完了。先上题目吧。
我一共用了三种方法解这道题目,第一种在POJ上运行结果为“超时”,第二种运行同样超时,第三种为错误(我也不知道哪里错啦,如果有看出来的还望指正)。
第一种方法很长,代码比较繁琐,尤其是冒泡排序那一段,我第一次的代码计算量比标准方法大了很多。以下为代码:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
void translator(string &a) //定义translator函数进行转换字母
{
for (size_t i = 0; i < a.size(); i++) {
if (a[i] == '1') {
a[i] = '1';
} else if (a[i] == 'A' || a[i] == 'B' || a[i] == 'C' || a[i] == '2') {
a[i] = '2';
} else if (a[i] == 'D' || a[i] == 'E' || a[i] == 'F' || a[i] == '3') {
a[i] = '3';
} else if (a[i] == 'G' || a[i] == 'H' || a[i] == 'I' || a[i] == '4') {
a[i] = '4';
} else if (a[i] == 'J' || a[i] == 'K' || a[i] == 'L' || a[i] == '5') {
a[i] = '5';
} else if (a[i] == 'M' || a[i] == 'N' || a[i] == 'O' || a[i] == '6') {
a[i] = '6';
} else if (a[i] == 'P' || a[i] == 'R' || a[i] == 'S' || a[i] == '7') {
a[i] = '7';
} else if (a[i] == 'T' || a[i] == 'U' || a[i] == 'V' || a[i] == '8') {
a[i] = '8';
} else if (a[i] == 'W' || a[i] == 'X' || a[i] == 'Y' || a[i] == '9') {
a[i] = '9';
}
}
}
void deletor(string &a) //定义translator函数删除无关字符
{
a.erase( remove(a.begin(), a.end(), '-'), a.end() )
//在容器中, 删除[begin,end)之间的所有值等于'-'、'Q'、'Z'的值.
a.erase( remove(a.begin(), a.end(), 'Q'), a.end() );
a.erase( remove(a.begin(), a.end(), 'Z'), a.end() );
}
void adder(string &a) //加入电话中的连字符,标准输出
{
a.push_back('-');
swap(a[7], a[6]);
swap(a[6], a[5]);
swap(a[5], a[4]);
swap(a[4], a[3]);
}
//int main(){ //检验两个转换函数是否正确
// string s; //结果:正确
// while( cin >> s){
// translator(s);
// deletor(s);
// cout << s << endl;
// }
//}
int main()
{
int n; //输入电话号码个数
while (cin >> n) { //进行输入操作
vector<string> directory; //n个电话作为一个数组
for (int i = 0; i < n; i++) {
string s;
cin >> s;
directory.push_back(s);
}
for (int i = 0; i < n; i++) { //转换操作
translator(directory[i]);
} //转换完成
for (int i = 0; i < n; i++) { //由小到大进行排序,方便进行输出
for (int j = 0; j < n; j++) {
if (directory[i] < directory[j]) {
swap(directory[j], directory[i]); //swap(**,**)交换两个数据位置
}
}
}
vector<int> count(n, 0); //n个零
for (int i = 0; i < n; i++) { //利用循环进行判断
for (int j = i + 1; j < n; j++) {
if (directory[i] == directory[j]) {
directory[j] = j;
count[i]++; //计数
}
}
if (count[i] != 0) {
cout << directory[i] << ' ' << count[i] + 1 << endl; //输出电话号码与次数
}
}
vector<int> count2(n, 0); //无重复项时的输出
if ( count == count2) {
cout << "无重复项" << endl;
}
}
以上定义的三个函数均是对电话号码进行操作,后续的两个方法也会用到。这种方法很繁琐,只用了最简单的循环、排序,是最容易的思路,不过这段代码可改进的地方还有很多,经过改进,有了第二段代码:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
void translator(string &a)
{
for (size_t i = 0; i < a.size(); i++) {
if (a[i] == '1') {
a[i] = '1';
} else if (a[i] == 'A' || a[i] == 'B' || a[i] == 'C' || a[i] == '2') {
a[i] = '2';
} else if (a[i] == 'D' || a[i] == 'E' || a[i] == 'F' || a[i] == '3') {
a[i] = '3';
} else if (a[i] == 'G' || a[i] == 'H' || a[i] == 'I' || a[i] == '4') {
a[i] = '4';
} else if (a[i] == 'J' || a[i] == 'K' || a[i] == 'L' || a[i] == '5') {
a[i] = '5';
} else if (a[i] == 'M' || a[i] == 'N' || a[i] == 'O' || a[i] == '6') {
a[i] = '6';
} else if (a[i] == 'P' || a[i] == 'R' || a[i] == 'S' || a[i] == '7') {
a[i] = '7';
} else if (a[i] == 'T' || a[i] == 'U' || a[i] == 'V' || a[i] == '8') {
a[i] = '8';
} else if (a[i] == 'W' || a[i] == 'X' || a[i] == 'Y' || a[i] == '9') {
a[i] = '9';
}
}
}
void deletor(string &a)
{
a.erase( remove(a.begin(), a.end(), '-'), a.end() );
a.erase( remove(a.begin(), a.end(), 'Q'), a.end() );
a.erase( remove(a.begin(), a.end(), 'Z'), a.end() );
}
void adder(string &a)
{
a.push_back('-');
swap(a[7], a[6]);
swap(a[6], a[5]);
swap(a[5], a[4]);
swap(a[4], a[3]);
}
int main(){
int n;
while (cin >> n) {
vector<string> directory;
for (int i = 0; i < n; i++) {
string s;
cin >> s;
directory.push_back(s);
}
for (int i = 0; i < n; i++) {
translator(directory[i]);
deletor(directory[i]);
adder(directory[i]);
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (directory[i] < directory[j]) {
swap(directory[j], directory[i]);
}
}
}
for (int i = 0; i < n; ++i) {
int j = i + 1;
int flag = 0;
while (j < n) {
if ( directory[i] == directory[j]) {
++j;
continue;
}
else if(j - i > 1){
cout << directory[i] << " " << (j - i) << endl;
i = j - 1;
flag++;
}
break;
}
if (j == n && j - i > 1) {
cout << directory[i] << " " << (j - i) << endl;
i = j - 1;
flag++;
}
if (flag == 0){
cout << "无重复项" << endl;
}
}
}
}
这段代码与第一段代码唯一的不同点在于排序阶段,这里的排序简洁了很多,用遍历的方式找到相同的项,相当于find if函数,这里也可以用find if函数,不过这个是在我写完这段代码后才知道的,就不做修改了;
第三段代码用了完全不同的思路(除了号码的转换函数),利用了map这种类型的特性:有序性;将转换后的号码输入进一个vector中,再将其中的元素拿出来,和一个计数用的int混装成map<string,int>的数对,int类型自动初始化为零(不需要我们再进行初始化),然后对这些数对进行遍历,对键值进行更改,最后输出(map类型会根据字典序自动进行排序),从而实现了map的计数功能。代码如下:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
using namespace std;
void translator(string &a)
{
for (size_t i = 0; i < a.size(); i++) {
if (a[i] == '1') {
a[i] = '1';
} else if (a[i] == 'A' || a[i] == 'B' || a[i] == 'C' || a[i] == '2') {
a[i] = '2';
} else if (a[i] == 'D' || a[i] == 'E' || a[i] == 'F' || a[i] == '3') {
a[i] = '3';
} else if (a[i] == 'G' || a[i] == 'H' || a[i] == 'I' || a[i] == '4') {
a[i] = '4';
} else if (a[i] == 'J' || a[i] == 'K' || a[i] == 'L' || a[i] == '5') {
a[i] = '5';
} else if (a[i] == 'M' || a[i] == 'N' || a[i] == 'O' || a[i] == '6') {
a[i] = '6';
} else if (a[i] == 'P' || a[i] == 'R' || a[i] == 'S' || a[i] == '7') {
a[i] = '7';
} else if (a[i] == 'T' || a[i] == 'U' || a[i] == 'V' || a[i] == '8') {
a[i] = '8';
} else if (a[i] == 'W' || a[i] == 'X' || a[i] == 'Y' || a[i] == '9') {
a[i] = '9';
}
}
}
void deletor(string &a)
{
a.erase( remove(a.begin(), a.end(), '-'), a.end() );
a.erase( remove(a.begin(), a.end(), 'Q'), a.end() );
a.erase( remove(a.begin(), a.end(), 'Z'), a.end() );
}
void adder(string &a)
{
a.push_back('-');
swap(a[7], a[6]);
swap(a[6], a[5]);
swap(a[5], a[4]);
swap(a[4], a[3]);
}
void map_cout(map<string, int> & m){
map<string, int>::iterator it = m.begin();
map<string, int>::iterator end = m.end();
int flag = 0;
while (it != end) {
if(it->second != 1){
cout << it->first << " " << it->second << endl;
flag++;
}
++it;
}
if(flag == 0){
cout << "无重复项" << endl;
}
cout << endl;
}
int main(){
int n;
while (cin >> n) {
vector<string> directory;
map<string,int> m;
for (int i = 0; i < n; i++) {
string s;
cin >> s;
directory.push_back(s);
}
for (int i = 0; i < n; i++) {
translator(directory[i]);
deletor(directory[i]);
adder(directory[i]);
}
int a = directory.size();
for (int i = 0; i < a; ++i) {
++m[directory[i]];
}
map_cout(m);
}
}
破案啦!!!POJ界面的显示为英文,我一般直接翻译成中文,最后那个“无重复项 ”也是中文的,自然过不了POJ的编译器,希望看到的人注意这个问题咯。
除了这一块,晚上还对第三段代码做了些精简,主要的修改在于主函数中的循环,观察代码后发现最后的循环过于繁冗,并且采用的方式都是for (int i = 0; i < n; i++) {......}的循环,因此可以进行合并的操作。此外,在原来的 adder函数中,连续swap的操作可以替换为简便的insert操作,translater函数也进行了细微调整。改正后如下:
#include <iostream>
#include <string>
#include <algorithm>
#include <map>
using namespace std;
void translator(string &a)
{
for (size_t i = 0; i < a.size(); i++) {
if (a[i] == 'A' || a[i] == 'B' || a[i] == 'C') {
a[i] = '2';
} else if (a[i] == 'D' || a[i] == 'E' || a[i] == 'F') {
a[i] = '3';
} else if (a[i] == 'G' || a[i] == 'H' || a[i] == 'I') {
a[i] = '4';
} else if (a[i] == 'J' || a[i] == 'K' || a[i] == 'L') {
a[i] = '5';
} else if (a[i] == 'M' || a[i] == 'N' || a[i] == 'O') {
a[i] = '6';
} else if (a[i] == 'P' || a[i] == 'R' || a[i] == 'S') {
a[i] = '7';
} else if (a[i] == 'T' || a[i] == 'U' || a[i] == 'V') {
a[i] = '8';
} else if (a[i] == 'W' || a[i] == 'X' || a[i] == 'Y') {
a[i] = '9';
}
}
}
void deletor(string &a)
{
a.erase( remove(a.begin(), a.end(), '-'), a.end() );
a.erase( remove(a.begin(), a.end(), 'Q'), a.end() );
a.erase( remove(a.begin(), a.end(), 'Z'), a.end() );
}
void adder(string &a)
{
a.insert(a.begin() + 3, '-');
}
void map_cout(const map<string, int> & m)
{
map<string, int>::const_iterator it = m.begin();
map<string, int>::const_iterator end = m.end();
bool flag = false;
while (it != end) {
if (it->second != 1) {
cout << it->first << " " << it->second << endl;
flag = true;
}
++it;
}
if (flag == false) {
cout << "No duplicates." << endl;
}
}
int main()
{
int n;
while (cin >> n) {
map<string, int> m;
for (int i = 0; i < n; i++) {
string s;
cin >> s;
translator(s);
deletor(s);
adder(s);
++m[s];
}
map_cout(m);
}
}