统计范围内的元音字符串数

98 阅读2分钟

🎈 算法并不一定都是很难的题目,也有很多只是一些代码技巧,多进行一些算法题目的练习,可以帮助我们开阔解题思路,提升我们的逻辑思维能力,也可以将一些算法思维结合到业务代码的编写思考中。简而言之,平时进行的算法习题练习带给我们的好处一定是不少的,所以让我们一起来养成算法练习的习惯。今天练习的题目是一道比较简单的题目 ->统计范围内的元音字符串数

问题描述

给你一个下标从  0  开始的字符串数组  words  以及一个二维整数数组  queries 。

每个查询  queries[i] = [li, ri]  会要求我们统计在  words  中下标在  li  到  ri  范围内(包含  这两个值)并且以元音开头和结尾的字符串的数目。

返回一个整数数组,其中数组的第  i  个元素对应第  i  个查询的答案。

注意: 元音字母是  'a''e''i''o'  和  'u' 。

示例 1:

输入: words = ["aba","bcb","ece","aa","e"], queries = [[0,2],[1,4],[1,1]]
输出: [2,3,0]
解释: 以元音开头和结尾的字符串是 "aba""ece""aa""e" 。
查询 [0,2] 结果为 2(字符串 "aba""ece")。
查询 [1,4] 结果为 3(字符串 "ece""aa""e")。
查询 [1,1] 结果为 0 。
返回结果 [2,3,0] 。

示例 2:

输入: words = ["a","e","i"], queries = [[0,2],[0,1],[2,2]]
输出: [3,2,1]
解释: 每个字符串都满足这一条件,所以返回 [3,2,1]

提示:

  • 1 <= words.length <= 10^5
  • 1 <= words[i].length <= 40
  • words[i]  仅由小写英文字母组成
  • sum(words[i].length) <= 3 * 10^5
  • 1 <= queries.length <= 10^5
  • 0 <= queries[j][0] <= queries[j][1] < words.length

思路分析

首先我们要先理解一下题目的意思,题目会给我们一个下标从  0  开始的字符串数组  words  以及一个二维整数数组  queries 。每个查询  queries[i] = [li, ri]  会要求我们统计在  words  中下标在  li  到  ri  范围内(包含  这两个值)并且以元音开头和结尾的字符串的数目。我们应该返回一个整数数组,其中数组的第  i  个元素对应第  i  个查询的答案。也就是说我们主要需要进行两个操作:

  • 1、判断字符串是否以元音字母开头和结尾;

这里我们只要知道什么是元音字母就可以直接判断字符串的开头和结尾是否为元音字母,因为words[i]  仅由小写英文字母组成,所以元音字母为["a", "e", "i", "o", "u"],我们可以直接使用includes来判断字符串是否以元音字母开头和结尾。

const vowel = ["a", "e", "i", "o", "u"];
vowel.includes(words[i][0]) &&
      vowel.includes(words[i][words[i].length - 1]
  • 2、统计queries[i]查询范围内满足条件的字符串个数

因为queries为一个数组,所以我们需要进行多次查询区间查询,这是我们应该要想到可以使用前缀和来进行解题,我们想要计算[i,j]区间中满足条件的字符串个数,如果我们知道[0,i]和[0,j]区间中满足条件的字符串个数的话,[i,j]区间满足条件的字符串个数 = [0,j]区间中满足条件的字符串个数 - [0,i]区间中满足条件的字符串个数,所以我们可以先算出数组中满足条件的字符串的前缀和。

const cnt = new Array(words.length).fill(0);
const vowel = ["a", "e", "i", "o", "u"];
for (let i = 0; i < words.length; i++) {
  cnt[i] =
    (cnt[i - 1] || 0) +
    (vowel.includes(words[i][0]) &&
    vowel.includes(words[i][words[i].length - 1])
      ? 1
      : 0);
}

得到前缀和数组 cnt 后,我们便能快速计算出每个区间中满足条件的字符串个数了:

const res = [];
queries.forEach((item) => {
  res.push(cnt[item[1]] - (cnt[item[0] - 1] || 0));
});

AC 代码

完整代码如下:

/**
 * @param {string[]} words
 * @param {number[][]} queries
 * @return {number[]}
 */
var vowelStrings = function (words, queries) {
  const cnt = new Array(words.length).fill(0);
  const vowel = ["a", "e", "i", "o", "u"];
  for (let i = 0; i < words.length; i++) {
    cnt[i] =
      (cnt[i - 1] || 0) +
      (vowel.includes(words[i][0]) &&
      vowel.includes(words[i][words[i].length - 1])
        ? 1
        : 0);
  }
  const res = [];
  queries.forEach((item) => {
    res.push(cnt[item[1]] - (cnt[item[0] - 1] || 0));
  });
  return res;
};

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,在此谢谢大家的支持,我们下文再见 🙌。