版权声明:本文为博主原创文章,博客地址:https://blog.csdn.net/qq_41855420,未经博主允许不得转载。 https://blog.csdn.net/qq_41855420/article/details/89604744
给出一个字符串数组words组成的一本英语词典。从中找出最长的一个单词,该单词是由words词典中其他单词逐步添加一个字母组成。若其中有多个可行的答案,则返回答案中字典序最小的单词。
若无答案,则返回空字符串。
示例 1:
输入:
words = ["w","wo","wor","worl", "world"]
输出: "world"
解释:
单词"world"可由"w", "wo", "wor", 和 "worl"添加一个字母组成。
示例 2:
输入:
words = ["a", "banana", "app", "appl", "ap", "apply", "apple"]
输出: "apple"
解释:
"apply"和"apple"都能由词典中的单词组成。但是"apple"得字典序小于"apply"。
注意:
所有输入的字符串都只包含小写字母。
words数组长度范围为[1,1000]。
words[i]的长度范围为[1,30]。
思路分析: 我们首先按照字典升序排序words,并且新建set用于存放由words词典中其他单词逐步添加一个字母组成的单词。
然后从前往后扫描words,如果word是合法字符串(该单词是由words词典中其他单词逐步添加一个字母组成),则它的长度 == 1,或者word的前wordSize - 1组成的单词是由words词典中其他单词逐步添加一个字母组成的单词。
class Solution {
public:
string longestWord(vector<string>& words) {
string res = "";
set<string> mySet;//用于存放由words词典中其他单词逐步添加一个字母组成的单词
sort(words.begin(), words.end());//按照字典升序排序
for (auto &word : words) {
int wordSize = word.size();
if (wordSize == 1 || mySet.find(word.substr(0, word.size() - 1)) != mySet.end()) {
//当word的长度为1,或者word的前wordSize - 1组成的单词是由words词典中其他单词逐步添加一个字母组成的单词,这时word也是合法的
mySet.insert(word);
if (wordSize > res.size()) {//更新最大长度的单词,由于words已经按照字典升序排序,所以只要考虑长度
res = word;
}
}
}
return res;
}
};
方法二:这种单词的搜索,一般都会使用前缀树(字典树)的数据结构进行辅助。关于前缀树请翻阅 LeetCode 实现Trie(前缀树)
//前缀树的程序表示
class TrieNode {
public:
bool isWord;//当前节点为结尾是否是单词
vector<TrieNode*> children;
TrieNode() : isWord(false), children(26, nullptr) {}
~TrieNode() {
for (TrieNode* child : children)
if (child) delete child;
}
};
class Solution {
public:
string resStr = "";//存储结果
TrieNode *trieRoot;//构建的单词后缀树
string longestWord(vector<string>& words) {
trieRoot = new TrieNode();
for (auto &word : words) {
addWord(word);
}
string tempStr = "";
myFind(trieRoot, tempStr);
return resStr;
}
//在树中插入一个单词的方法实现
void addWord(string &word) {
TrieNode *ptr = trieRoot;//扫描这棵树,将word插入
//将word的字符逐个插入
for (auto ch : word) {
if (ptr->children[ch - 'a'] == NULL) {
ptr->children[ch - 'a'] = new TrieNode();
}
ptr = ptr->children[ch - 'a'];
}
ptr->isWord = true;//标记为单词
}
//扫描root,寻找最长的合法单词
void myFind(TrieNode *root, string &resWord) {
if (root != NULL) {
//搜索它的二十六个指针
for (int index = 0; index < 26; ++index) {
//只有当这个子指针指向的字母是一个单词的尾端,以这个字母结尾的单词才能是一个合法的结果
if (root->children[index] != NULL && root->children[index]->isWord) {
string newStr = resWord + char('a' + index);
if (newStr.size() > resStr.size()) {
resStr = newStr;
}
myFind(root->children[index], newStr);
}
}
}
}
};