1、题干
给定字符串 s
和字符串数组 words
, 返回 words[i]
中是s
的子序列的单词个数 。
字符串的 子序列 是从原始字符串中生成的新字符串,可以从中删去一些字符(可以是none),而不改变其余字符的相对顺序。
- 例如,
“ace”
是“abcde”
的子序列。
示例 1:
输入: s = "abcde", words = ["a","bb","acd","ace"]
输出: 3
解释: 有三个是 s 的子序列的单词: "a", "acd", "ace"。
Example 2:
输入: s = "dsahjpjauf", words = ["ahjpjau","ja","ahbwzgqnuk","tnmlanowax"]
输出: 2
提示:
1 <= s.length <= 5 * 104
1 <= words.length <= 5000
1 <= words[i].length <= 50
words[i]
和s 都只由小写字母组成。
Problem: 792. 匹配子序列的单词数
2、思路
二分查找
- 按字母表顺序把字符串
s
中所有字符的下标升序存入二维数组idxMatrix
- 判断数组
words
中任意字符串w
是否s
的子序列,只需要判断w
中任意字符c
比前一个字符 在s
中的下标更大。其中查找c
在s
中的下标时,使用二分查找算法
3、Code
function numMatchingSubseq(s: string, words: string[]): number {
const CA = 'a'.charCodeAt(0), idxMatrix = new Array(26).fill(0).map(() => []);
for (let i = 0; i < s.length; i++) {
const ci = s[i].charCodeAt(0) - CA;
idxMatrix[ci].push(i);
}
function find(nums: number[] = [], k: number) {
let l = 0, r = nums.length - 1;
while (l <= r) {
const m = ((l + r) / 2) >> 0;
if (nums[m] > k) {
if (nums[m - 1] > k) r = m - 1;
else return nums[m];
} else {
l = m + 1;
}
}
return -1;
}
let res = 0;
loop: for (const w of words) {
let preIdx = -1;
for (const c of w) {
const ci = c.charCodeAt(0) - CA;
const ni = find(idxMatrix[ci], preIdx);
if (ni < 0) continue loop;
preIdx = ni;
}
res++;
}
return res;
};
4、复杂度
- 时间复杂度:
- 空间复杂度: