03.02.12 练习题目(第 07 天)
1. 0211. 添加与搜索单词 - 数据结构设计
1.1 题目大意
要求:设计一个数据结构,支持「添加新单词」和「查找字符串是否与任何先前添加的字符串匹配」。
实现词典类 WordDictionary:
WordDictionary()
初始化词典对象。void addWord(word)
将word
添加到数据结构中,之后可以对它进行匹配bool search(word)
如果数据结构中存在字符串与word
匹配,则返回True
;否则,返回False
。word
中可能包含一些.
,每个.
都可以表示任何一个字母。
说明:
- 1 ≤ w o r d . l e n g t h ≤ 25 1 \le word.length \le 25 1≤word.length≤25。
addWord
中的word
由小写英文字母组成。search
中的word
由'.'
或小写英文字母组成。- 最多调用
1
0
4
10^4
104 次
addWord
和search
。
示例:
输入:
["WordDictionary","addWord","addWord","addWord","search","search","search","search"]
[[],["bad"],["dad"],["mad"],["pad"],["bad"],[".ad"],["b.."]]
输出:
[null,null,null,null,false,true,true,true]
解释:
WordDictionary wordDictionary = new WordDictionary();
wordDictionary.addWord("bad");
wordDictionary.addWord("dad");
wordDictionary.addWord("mad");
wordDictionary.search("pad"); // 返回 False
wordDictionary.search("bad"); // 返回 True
wordDictionary.search(".ad"); // 返回 True
wordDictionary.search("b.."); // 返回 True
我的答案:
class TrieNode {
public:
std::unordered_map<char, TrieNode*> children;
bool isEndOfWord;
TrieNode() : isEndOfWord(false) {}
};
class WordDictionary {
private:
TrieNode* root;
public:
WordDictionary() {
root = new TrieNode();
}
void addWord(std::string word) {
TrieNode* current = root;
for (char ch : word) {
if (current->children.find(ch) == current->children.end()) {
current->children[ch] = new TrieNode();
}
current = current->children[ch];
}
current->isEndOfWord = true;
}
bool search(std::string word) {
return searchHelper(word, 0, root);
}
private:
bool searchHelper(const std::string& word, int index, TrieNode* node) {
if (index == word.size()) {
return node->isEndOfWord;
}
char ch = word[index];
if (ch == '.') {
for (auto& pair : node->children) {
if (searchHelper(word, index + 1, pair.second)) {
return true;
}
}
return false;
} else {
if (node->children.find(ch) == node->children.end()) {
return false;
}
return searchHelper(word, index + 1, node->children[ch]);
}
}
};
心得:
- 注意
searchHelper
函数的返回值,以及search
函数的返回值。
2. 0648. 单词替换
2.1 题目大意
描述:给定一个由许多词根组成的字典列表 dictionary
,以及一个句子字符串 sentence
。
要求:将句子中有词根的单词用词根替换掉。如果单词有很多词根,则用最短的词根替换掉他。最后输出替换之后的句子。
说明:
- 1 ≤ d i c t i o n a r y . l e n g t h ≤ 1000 1 \le dictionary.length \le 1000 1≤dictionary.length≤1000。
- 1 ≤ d i c t i o n a r y [ i ] . l e n g t h ≤ 100 1 \le dictionary[i].length \le 100 1≤dictionary[i].length≤100。
dictionary[i]
仅由小写字母组成。- 1 ≤ s e n t e n c e . l e n g t h ≤ 1 0 6 1 \le sentence.length \le 10^6 1≤sentence.length≤106。
sentence
仅由小写字母和空格组成。sentence
中单词的总量在范围 [ 1 , 1000 ] [1, 1000] [1,1000] 内。sentence
中每个单词的长度在范围 [ 1 , 1000 ] [1, 1000] [1,1000] 内。sentence
中单词之间由一个空格隔开。sentence
没有前导或尾随空格。
示例:
输入:dictionary = ["cat","bat","rat"], sentence = "the cattle was rattled by the battery"
输出:"the cat was rat by the bat"
输入:dictionary = ["a","b","c"], sentence = "aadsfasf absbs bbab cadsfafs"
输出:"a a b c"
我的答案:
class Solution {
public:
string replaceWords(vector<string>& dictionary, string sentence) {
// 对字典进行排序,确保最短的前缀在前
sort(dictionary.begin(), dictionary.end());
// 使用istringstream分割句子
istringstream iss(sentence);
string word;
string result = "";
while (iss >> word) {
// 查找最短的前缀
string prefix = findPrefix(dictionary, word);
if (!prefix.empty()) {
result += prefix + " ";
} else {
result += word + " ";
}
}
// 去掉最后一个多余的空格
if (!result.empty()) {
result.pop_back();
}
return result;
}
private:
string findPrefix(const vector<string>& dictionary, const string& word) {
for (const string& prefix : dictionary) {
if (word.substr(0, prefix.size()) == prefix) {
return prefix;
}
}
return "";
}
};
心得:
- 注意
findPrefix
函数的返回值,以及replaceWords
函数的返回值。
3. 0676. 实现一个魔法字典
3.1 题目大意
要求:设计一个使用单词表进行初始化的数据结构。单词表中的单词互不相同。如果给出一个单词,要求判定能否将该单词中的一个字母替换成另一个字母,是的所形成的新单词已经在够构建的单词表中。
实现 MagicDictionary 类:
MagicDictionary()
初始化对象。void buildDict(String[] dictionary)
使用字符串数组dictionary
设定该数据结构,dictionary
中的字符串互不相同。bool search(String searchWord)
给定一个字符串searchWord
,判定能否只将字符串中一个字母换成另一个字母,使得所形成的新字符串能够与字典中的任一字符串匹配。如果可以,返回True
;否则,返回False
。
说明:
- 1 ≤ d i c t i o n a r y . l e n g t h ≤ 100 1 \le dictionary.length \le 100 1≤dictionary.length≤100。
- 1 ≤ d i c t i o n a r y [ i ] . l e n g t h ≤ 100 1 \le dictionary[i].length \le 100 1≤dictionary[i].length≤100。
dictionary[i]
仅由小写英文字母组成。dictionary
中的所有字符串互不相同。- 1 ≤ s e a r c h W o r d . l e n g t h ≤ 100 1 \le searchWord.length \le 100 1≤searchWord.length≤100。
searchWord
仅由小写英文字母组成。buildDict
仅在search
之前调用一次。- 最多调用
100
100
100 次
search
。
示例:
输入
["MagicDictionary", "buildDict", "search", "search", "search", "search"]
[[], [["hello", "leetcode"]], ["hello"], ["hhllo"], ["hell"], ["leetcoded"]]
输出
[null, null, false, true, false, false]
解释
MagicDictionary magicDictionary = new MagicDictionary();
magicDictionary.buildDict(["hello", "leetcode"]);
magicDictionary.search("hello"); // 返回 False
magicDictionary.search("hhllo"); // 将第二个 'h' 替换为 'e' 可以匹配 "hello" ,所以返回 True
magicDictionary.search("hell"); // 返回 False
magicDictionary.search("leetcoded"); // 返回 False
我的答案:
class MagicDictionary {
private:
unordered_set<string> dict;
public:
MagicDictionary() {
// 初始化字典
}
void buildDict(vector<string> dictionary) {
for (const string& word : dictionary) {
dict.insert(word);
}
}
bool search(string searchWord) {
for (const string& word : dict) {
if (isOneCharDifferent(searchWord, word)) {
return true;
}
}
return false;
}
private:
bool isOneCharDifferent(const string& word1, const string& word2) {
if (word1.size() != word2.size()) {
return false;
}
int diffCount = 0;
for (size_t i = 0; i < word1.size(); ++i) {
if (word1[i] != word2[i]) {
++diffCount;
if (diffCount > 1) {
return false;
}
}
}
return diffCount == 1;
}
};
心得:
- 字典的建立,可以先用unordered_set,然后用insert插入
- 字典的查找,可以先用unordered_set,然后用find查找
- 字符串的比较,可以先用string,然后用==比较
- 字符串的替换,可以先用string,然后用[]替换
- 字符串的插入,可以先用string,然后用+插入
- 字符串的删除,可以先用string,然后用substr删除