携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第26天,点击查看活动详情
刷题的日常-2022年8月21日
一天一题,保持脑子清爽
检查单词是否为句中其他单词的前缀
来自leetcode的 1455 题,题意如下:
给你一个字符串 sentence 作为句子并指定检索词为 searchWord ,其中句子由若干用 单个空格 分隔的单词组成。请你检查检索词 searchWord 是否为句子 sentence 中任意单词的前缀。
如果searchWord 是某一个单词的前缀,则返回句子sentence 中该单词所对应的下标(下标从 1 开始)。如果 searchWord 是多个单词的前缀,则返回匹配的第一个单词的下标(最小下标)。如果 searchWord 不是任何单词的前缀,则返回 -1 。
字符串 s 的 前缀 是 s 的任何前导连续子字符串。
理解题意
我们可以从题意中提取的条件如下:
- 题目给定了两个字符串
- 一个是句子,由空格分隔单词
- 一个是单词
- 要求我们找出句子中的由第二个字符串构成前缀的单词
- 如果有多个,返回索引最小的一个
- 如果没有,返回-1
做题思路
我们可以暴力用单词一个一个去匹配,最先匹配到的就返回单词的位置,这个很简单,这里提供第二种思路。
前缀树:前缀树是一棵由单词前缀构成的树,树根代表开始位置,我们可以将单词放进树之后再进行匹配。因为要返回最先匹配的单词位置,所以我们放进去之后不需要覆盖原有的前缀:
- 将句子用 空格 进行切分
- 构建前缀树,将单词 和 第一次出现的位置放到树中
- 对查找的单词进行匹配
- 匹配得到返回位置
- 否则返回-1
代码实现
代码实现如下:由于要构建前缀树,所以时间复杂度会比较高
public class Solution {
public int isPrefixOfWord(String sentence, String searchWord) {
String[] words = sentence.split(" ");
Tire tire = new Tire(-1);
for (int i = 0; i < words.length; i++) {
tire.insert(words[i], i + 1);
}
for (int i = 0; i < searchWord.length(); i++) {
char c = searchWord.charAt(i);
tire = tire.next[c - 'a'];
if (tire == null) {
return -1;
}
}
return tire.idx;
}
static class Tire {
int idx;
Tire[] next = new Tire[26];
public Tire(int idx) {
this.idx = idx;
}
public void insert(String word, int idx) {
Tire tmp = this;
char c;
for (int i = 0; i < word.length(); i++) {
c = word.charAt(i);
tmp = tmp.next[c - 'a'] = tmp.next[c - 'a'] == null ? new Tire(idx) : tmp.next[c - 'a'];
}
}
}
}