题目
给你一个字符串 sentence
作为句子并指定检索词为 searchWord
,其中句子由若干用 单个空格 分隔的单词组成。请你检查检索词 searchWord
是否为句子 sentence
中任意单词的前缀。
如果 searchWord
是某一个单词的前缀,则返回句子 sentence
中该单词所对应的下标(下标从 1 开始)。如果 searchWord
是多个单词的前缀,则返回匹配的第一个单词的下标(最小下标)。如果 searchWord
不是任何单词的前缀,则返回 -1
。
字符串 s
的 前缀 是 s
的任何前导连续子字符串。
示例 1:
输入:sentence = "i love eating burger", searchWord = "burg"
输出:4
解释:"burg" 是 "burger" 的前缀,而 "burger" 是句子中第 4 个单词。
示例 2:
输入:sentence = "this problem is an easy problem", searchWord = "pro"
输出:2
解释:"pro" 是 "problem" 的前缀,而 "problem" 是句子中第 2 个也是第 6 个单词,但是应该返回最小下标 2 。
示例 3:
输入:sentence = "i am tired", searchWord = "you"
输出:-1
解释:"you" 不是句子中任何单词的前缀。
提示:
1 <= sentence.length <= 100
1 <= searchWord.length <= 10
sentence
由小写英文字母和空格组成。searchWord
由小写英文字母组成。
解题
方法一:Java API(split()
+ startsWith()
)
思路
如果用上 Java API,那这题就再简单不过了:
直接把字符串按照空格分割(split()
)为字符串数组然后遍历数组,如果某个元素以 serachWord
为前缀(startWith()
),那么就直接返回对应下标加一。遍历完成后还没返回说明没有符合的单词,直接返回 -1
。
代码
class Solution {
public int isPrefixOfWord(String sentence, String searchWord) {
String[] words = sentence.split(" ");
for (int i = 0; i < words.length; ++i) {
if (words[i].startsWith(searchWord)) return i + 1;
}
return -1;
}
}
方法二:双指针 Java API / C++ STL
思路
由于 C++ 没有像 Java 那么好用的用来分割字符串 API(split()
),所以我们来自己实现一个。
也很简单,维护一个计数(count
)表示目前单词的位置,两个指针:一个应该指向单词开头(start
/ begin
),另一个应该指向单词结尾的下一个字符(也就是空格)(end
)。初始化前指针指向 s[0]
,后指针指向下一个字符(毕竟单词再短也至少有一个字符),然后开始遍历:
对于每一次循环,后指针先向后推找到最近的一个空格,那么 就是一个单词,判断这个单词前缀是否含有 searchWord
如果有就直接返回计数,否则计数自增,前指针和后指针都移动到后指针的下一个元素上继续下一次遍历。
这里判断前缀可以使用 Java API(startWith()
) 或 C++ STL(find()
)(如果在字串中找到前缀的位置为 0
那就说明包含前缀)。也可以写个方法一个字符一个字符比较。
代码
class Solution {
public:
int isPrefixOfWord(string sentence, string search_word) {
int count = 1;
for (auto begin = sentence.begin(), end = begin + 1; begin < sentence.end();) {
while (end < sentence.end() && *end != ' ') ++end;
string word(begin, end);
if (word.find(search_word) == 0) return count;
++count;
begin = ++end;
}
return -1;
}
};
isSectionValid()
用来判断前缀是否存在于该字串。
class Solution {
char[] sentence, searchWord;
int searchWordLen;
public int isPrefixOfWord(String _sentence, String _searchWord) {
sentence = _sentence.toCharArray();
searchWord = _searchWord.toCharArray();
int n = sentence.length;
searchWordLen = searchWord.length;
for (int start = 0, end = 1, count = 1; start < n;) {
while (end < n && sentence[end] != ' ') ++end;
if (isSectionValid(start, end)) return count;
++count;
start = ++end;
}
return -1;
}
boolean isSectionValid(int start, int end) {
if (end - start < searchWordLen) return false;
for (int i = 0; i < searchWordLen; ++i) {
if (sentence[start + i] != searchWord[i]) return false;
}
return true;
}
}
方法三:双指针 前缀树(字典树)
思路
要想把这题变得更复杂一点的话(虽然它本身只是个简单题)就上前缀树(Trie)吧。
具体前缀树的作用和实现见:【前缀树】实现 Trie (前缀树)。
(当然,再往复杂处用 KMP 什么的做也可以,但是没必要了)
(这题我看到单词前缀就想都没想上前缀树了,后来才看到解题里大家都是用 API 直接做的 ヽ(*。>Д<)o゜)
代码
class Trie {
public:
bool is_end;
Trie* children[26];
Trie() : is_end(false) {
for (int i = 0; i < 26; ++i) children[i] = nullptr;
}
void insert(string& word) {
Trie* node = this;
for (char ch : word) {
int idx = ch - 'a';
if (!node->children[idx]) node->children[idx] = new Trie();
node = node->children[idx];
}
node->is_end = true;
}
Trie* searchPrefix(string& word) {
Trie* node = this;
for (char ch : word) {
int idx = ch - 'a';
if (!node->children[idx]) return nullptr;
node = node->children[idx];
}
return node;
}
bool startsWith(string& word) {
return searchPrefix(word);
}
};
class Solution {
public:
int isPrefixOfWord(string sentence, string search_word) {
Trie trie;
int count = 1;
for (auto begin = sentence.begin(), end = begin + 1; begin < sentence.end();) {
while (end < sentence.end() && *end != ' ') ++end;
string word(begin, end);
trie.insert(word);
if (trie.startsWith(search_word)) return count;
++count;
begin = ++end;
}
return -1;
}
};
class Solution {
public int isPrefixOfWord(String sentence, String searchWord) {
String[] words = sentence.split(" ");
Trie trie = new Trie();
for (int i = 0; i < words.length; ++i) {
trie.insert(words[i]);
if (trie.startsWith(searchWord)) return i + 1;
}
return -1;
}
static class Trie {
boolean isEnd;
Trie[] children;
public Trie() {
isEnd = false;
children = new Trie[26];
}
void insert(String word) {
Trie node = this;
for (char ch : word.toCharArray()) {
int idx = ch - 'a';
if (node.children[idx] == null) node.children[idx] = new Trie();
node = node.children[idx];
}
node.isEnd = true;
}
Trie searchPrefix(String word) {
Trie node = this;
for (char ch : word.toCharArray()) {
int idx = ch - 'a';
if (node.children[idx] == null) return null;
node = node.children[idx];
}
return node;
}
boolean startsWith(String word) {
return searchPrefix(word) != null;
}
}
}
评论区