111

111

壹 ❀ 引

今天来做一道题目贼长,但做起来不难的题,为啥昨天前天没写呢,因为题目太简单了,没收获额外有用信息,已知的知识反复写就有些浪费时间了。今天的题目来自leetcode1455. 检查单词是否为句中其他单词的前缀,题目描述如下:

给你一个字符串 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" 不是句子中任何单词的前缀。

示例 4:

输入:sentence = "i use triple pillow", searchWord = "pill"
输出:4

示例 5:

输入:sentence = "hello from the other side", searchWord = "they"
输出:-1

提示:

1 <= sentence.length <= 100
1 <= searchWord.length <= 10
sentence 由小写英文字母和空格组成。
searchWord 由小写英文字母组成。
前缀就是紧密附着于词根的语素,中间不能插入其它成分,并且它的位置是固定的——-位于词根之前。

我们来简单分析题目,提取解题信息,再说解题思路。

贰 ❀ 解题思路

题目虽然看着贼长,要求其实很简单,给定一串字符sentence 作为句子,看句子中是否有某个单词的前缀为searchWord ,假设有或者有多个,返回第一个单词的下标(注意这里的下标从1开始),如果没有则返回-1。

由于题目已经清晰的给出了每个单词用空格分隔,因此这里我们完全可以使用split按空格切割成数组。其次,由于题目不存在大写情况,这里的searchWord 完全可以作为正则的匹配条件,所以我的本能第一是这样:

/**
 * @param {string} sentence
 * @param {string} searchWord
 * @return {number}
 */
var isPrefixOfWord = function (sentence, searchWord) {
    // 将searchWord作为正则匹配条件
    let regexp = new RegExp("^" + searchWord);
    //利用findIndex找到第一个符合条件的字符
    let index = sentence.split(" ").findIndex(item => regexp.test(item));
    //返回字符下标或者-1
    return index > -1 ? index + 1 : index;
};

比较遗憾,这段代码的效率并不高,只击败了百分之七的用户。

所以在想有没有更高效的做法,比如不用正则。这里我又想到了indexOf,此方法可以判断字符中是否包含某个字符,由于题目要求是单词前缀,所以indexOf不仅要有,获取的还必须是从0开始,比如:

"abc".indexOf("ab");//0 √
"aab".indexOf("ab");//1 ×

所以又有了这段实现:

/**
 * @param {string} sentence
 * @param {string} searchWord
 * @return {number}
 */
var isPrefixOfWord = function (sentence, searchWord) {
    // 直接判断每个单词的indexOf是否是0即可
    let index = sentence.split(" ").findIndex(item => item.indexOf(searchWord) === 0);
    return index > -1 ? index + 1 : index;
};

这段实现就快了很多,击败了百分之七十多的人。

有没有更绝的做法呢,我在评论区看到了一个"令人发指"的API,用起来那是相当过分!那就是ES6中新增的startsWith方法,此方法返回一个布尔值,用于判断参数字符串是否在原字符串的头部,比如:

'hi,echo'.startsWith('hi');//true
'hi,echo'.startsWith('echo');//false
'hi,echo'.startsWith('echo',3);//true

通过上面的例子可以发现此方法接受2个参数,第一个是你希望检索的字符,第二个可选,是你希望开始检索的下标,如果不提供则默认为0。

那么知道这个之后,我们就可以实现这段代码:

/**
 * @param {string} sentence
 * @param {string} searchWord
 * @return {number}
 */
var isPrefixOfWord = function (sentence, searchWord) {
    // 直接判断每个单词的indexOf是否是0即可
    let index = sentence.split(" ").findIndex(item => item.startsWith(searchWord));
    return index > -1 ? index + 1 : index;
};
111

然后,击败了99.47%的用户,哈哈哈哈,可能,这是我现在少有能感觉到的快乐吧。

心情不好,虽然这篇博客不长,还是破例用一张我喜欢的封面图,去学vue去了,那么这些话是我在对谁说呢?

上一篇:2018-10-10 在浏览器插件中读取JSON资源文件


下一篇:名称空间与作用域