一、题目
输入一些单词,找出所有满足如下条件的单词:该单词不能通过字母重排,得到输入文本中的另外一个单词。在判断是否满足条件时,字母不分大小写,但在输出时应保留输入中的大小写,按字典序进行排列(所有大写字母在所有小写字母的前面)。
样例输入:
ladder came tape soon leader acme RIDE lone Dreis peatScAlE orb eye Rides dealer NotE derail LaCeS drIednoel dire Disk mace Rob dries
样例输出:
Disk
NotE
derail
drIed
eye
ladder
soon
二、 思路分析,步骤和代码以及说明
1.思路分析
题目意思就是找一些单词,这些单词可以进行字母重排,比如come可以重排为omec,如果重排之后和文本中任意一个单词都不一样,就输出。
这题呢还是比较训练思维的,要先把所有字母变成小写的,然后把每个单词都排序,比如come按照大小顺序排出来后是cemo,再把它们放到map中统计。如果两个单词一模一样,就不用输出了。
2.步骤
一个一个输入单词并用vector把单词装进去→用tolower函数把所有大写字母变成小写的并排好序→用map映射看元素出现次数,没有出现过的话就添加进新的vector数组ans中→输出ans内容。
注意 两个数组,一个用来存原本的单词信息,一个用来存符合要求的单词信息。一个映射,用来判断单词是否出现过,如果第一次出现就让其出现次数从0变为1。
这样做可能开辟的内存空间比较多,但是他很快速并且容易理解。反正我写了很多段代码,这有这一段最好
3.代码
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<cctype>
#include<algorithm>
using namespace std;
map<string, int>cnt;
vector<string> words;
//把所有大写字母变成小写字母并排序
string transfer(const string& s) {
string ans = s;
for (int i = 0; i < ans.length(); i++) {
if (ans[i] >= 'A' && 'Z' >= ans[i])
ans[i] = tolower(ans[i]);
}
sort(ans.begin(), ans.end());
return ans;
}
int main() {
int n = 0;
string s;
while (cin >> s) {
if (s[0] == '#') break;
words.push_back(s);
string t;
t = transfer(s);
if (!cnt.count(t))cnt[t] = 0;//如果元素没有出现过就赋值0
cnt[t]++;//标记该元素已经出现过了
}
vector<string> ans;
for (int i = 0; i < words.size(); i++)
if (cnt[transfer(words[i])] == 1) ans.push_back(words[i]);//如果只出现过一次就添加进vector
sort(ans.begin(), ans.end());
for (int i = 0; i < ans.size(); i++)
cout << ans[i] << "\n";
return 0;
}
4.说明
map底层是红黑树实现的,具有自动排序的功能,有一对对的hash值,左边的叫关键字(key),右边的叫关键字的值(value)。

一一映射的关系中,一个名字对应一个电话号码,只要搜索名字,就能得到相应的电话号码,搜索电话号码也能得到相应的名字。map.count()是返回元素出现的次数。
文章讲述了如何使用C++编程解决一个算法问题:给定一组单词,找出那些不能通过重新排列字母形成其他单词的字符串。解决方案包括将单词转为小写并排序,利用map存储排序后的单词及其出现次数,最后输出仅出现一次的单词。
566

被折叠的 条评论
为什么被折叠?



