好长时间没写blog了,写一篇表示我还活着,还在看代码,还在准备笔试和面试。。。
兄弟的单词就是两个或多个单词有相同的字母,只是字母顺序不同,例如:abfs 和fabs。找到所给单词的兄弟单词。
方案一:使用数据结构 map<key,list>。兄弟单词共用一个签名key,key为单词内部排序后的词条,list存储同一key的单词集合;把相同key的兄弟单词组成一个链表。
代码:
#include<iostream>
#include<string>
#include<map>
using namespace std;
struct node
{
string word;
node* next;
};
int cmp(const void* p, const void* q)
{
return (*(char*)p) - (*(char*)q);
}
string ChangeWordToKey(string word)
{
int length = word.length();
char* pword = &word[0];
qsort(pword, length, sizeof(char), cmp);
return word;
}
void InsertWordToList(node* list, node* word)
{
node* p = list;
while(p->next != NULL)
p = p->next;
p->next = word;
}
void InsertWordsToMap(map<string, node*> &bromap, string word)
{
string key = ChangeWordToKey(word);
node* pword = new node();
pword->word = word;
pword->next = NULL;
if(bromap[key])
InsertWordToList(bromap[key], pword);
else
bromap[key] = pword;
}
void OutputList(node* list)
{
if(list == NULL)
return;
else
{
while(list != NULL)
{
cout<<list->word<<'\t';
list = list->next;
}
}
}
void OutputMap(map<string, node*> &bromap)
{
map<string, node*>::iterator it = bromap.begin();
for(; it != bromap.end(); ++it)
{
cout<<it->first<<": ";
OutputList(it->second);
cout<<endl;
}
}
void OutputBrotherWords(string* words, int length)
{
map<string, node*> bromap;
for(int i = 0; i < length; ++i)
InsertWordsToMap(bromap, words[i]);
OutputMap(bromap);
}
int main(int argc, char* argv[])
{
string words[10] = {"abc", "bca", "cba", "fgdes", "edss",
"ssde", "fffg", "fgff", "gfff", "sffdswe"};
OutputBrotherWords(words,10);
return 0;
}
方案二:使用trie树。trie树又称字典树,在面试题中关于“字符串”与“数字串”类型的问题中高频出现,非常实用。对于兄弟单词,兄弟单词公用一个key自不必说,只是trie的节点结构应该多出一个域list,用来存储key对应的兄弟单词。具体节点结构应该为:
struct TrieNode
{
bool isAWord;//is a word
TrieNode* next[BRANCHNUM];
std::vector<const char*> browords;
};
代码:
/*-----BrotherTrie.h-----*/
#ifndef BROTHERTRIE_H
#define BROTHERTRIE_H
#include<iostream>
#include<vector>
#define BRANCHNUM 26
/*trie node*/
struct TrieNode
{
bool isAWord;//is a word
TrieNode* next[BRANCHNUM];
std::vector<const char*> browords;
TrieNode():isAWord(false)
{
std::memset(next,NULL,sizeof(next));
}
};
/*trie class*/
class BroTrie
{
public:
TrieNode* root;
BroTrie() {root = new TrieNode();}
/*insert a word to brother trie*/
void insertAWord(const char* key, const char* word)
{
TrieNode* location = root;
while(*key)
{
if(location->next[*key - 'a'] == NULL)
{
TrieNode* tmp = new TrieNode();
location->next[*key - 'a'] = tmp;
}
location = location->next[*key - 'a'];
++key;
}
location->isAWord = true;
location->browords.push_back(word);
}
void outputBroWords(TrieNode* location)
{
if(location->isAWord)
{
std::vector<const char*>::iterator it = location->browords.begin();
for(; it != location->browords.end(); ++it)
printf("%s ",*it);
printf("\n");
}
for(int i = 0; i < BRANCHNUM; ++i)
if(location->next[i] != NULL)
outputBroWords(location->next[i]);
delete location;
}
};
#endif
/*-----BrotherTrie.cpp-----*/
#include<iostream>
#include"BrotherTrie.h"
using namespace std;
int cmp(const void* p, const void* q)
{
return (*(char*)p) - (*(char*)q);
}
int main()
{
BroTrie broWords;
string words[10] = {"abc", "bca", "cba", "fgdes", "edss",
"ssde", "fffg", "fgff", "gfff", "sffdswe"};
char* key; char* word;
for(int i = 0; i < 10; ++i)
{
word = &words[i][0];
int len = words[i].length();
key = new char[len+1];
strcpy(key, word);
qsort(key, len, sizeof(char), cmp);
broWords.insertAWord(key, word);
}
broWords.outputBroWords(broWords.root);
return 0;
}