给出一个字符串数组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]。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-word-in-dictionary
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:这种单词的搜索,一般都会使用前缀树(字典树)的数据结构进行辅助。关于前缀树请翻阅 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'] == nullptr)
{
ptr->children[ch - 'a'] = new TrieNode();
}
ptr = ptr->children[ch - 'a'];//转入下一个节点
}
ptr->isWord = true;//到最后一个节点 标记为单词
}
//扫描root 寻找最长的合法单词
void myFind(TrieNode *root,string &resWord)
{
if(!root)
return;
//搜索它的二十六个指针
for(int index = 0;index < 26; ++index)
{
//只有当这个子指针指向的字母是一个单词的尾端,以这个字母结尾的单词才能是一个合法的结果
if(root->children[index] != nullptr && root->children[index]->isWord)
{
string newStr = resWord + char('a' + index);//添加一个新字符
if(newStr.size() > resStr.size())
{
resStr = newStr;//更新最长的合法单词
}
myFind(root->children[index],newStr);
}
}
}
};