Skip to content

Commit d43776a

Browse files
Create 792. 匹配子序列的单词数.md
1 parent 61cb8c9 commit d43776a

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#### 792. 匹配子序列的单词数
2+
3+
难度:中等
4+
5+
---
6+
7+
给定字符串 `s` 和字符串数组 `words`, 返回 _`words[i]` 中是`s`的子序列的单词个数_
8+
9+
字符串的 **子序列** 是从原始字符串中生成的新字符串,可以从中删去一些字符(可以是none),而不改变其余字符的相对顺序。
10+
11+
* 例如, `“ace”``“abcde”` 的子序列。
12+
13+
**示例 1:**
14+
15+
```
16+
输入: s = "abcde", words = ["a","bb","acd","ace"]
17+
输出: 3
18+
解释: 有三个是 s 的子序列的单词: "a", "acd", "ace"。
19+
```
20+
21+
**Example 2:**
22+
23+
```
24+
输入: s = "dsahjpjauf", words = ["ahjpjau","ja","ahbwzgqnuk","tnmlanowax"]
25+
输出: 2
26+
```
27+
28+
**提示:**
29+
30+
* `1 <= s.length <= 5 * 10^4`
31+
* `1 <= words.length <= 5000`
32+
* `1 <= words[i].length <= 50`
33+
* `words[i]`和 s 都只由小写字母组成。
34+
35+
---
36+
37+
因为题目要求子序列是不改变字符的相对顺序的序列,那么将字符串 `s` 中的所有字符下标按顺序存放到 26 个字母表的下标列表中,针对 `words` 字符串数组中的每一个字符串,检查每个字符在字符串 `s` 中的下标是否按升序排序即可。
38+
39+
但是需要注意的是,上述检查的过程中需要用到二分查找,否则会超时。寻找的内容是大于 `index` (初始值为 `-1` )的最小下标,例如在下标数组 `{0, 1, 4, 6}` 中寻找大于 `index = 2` 最小下标,即下标为 `2`,值为 `4`,接着将 `index` 赋值为 `4` 接着寻找下一个下标。
40+
41+
```java
42+
class Solution {
43+
public int numMatchingSubseq(String s, String[] words) {
44+
ArrayList<Integer>[] list = new ArrayList[26];
45+
for(int i = 0; i < 26; i++){
46+
list[i] = new ArrayList<>();
47+
}
48+
for(int i = 0; i < s.length(); i++){
49+
list[s.charAt(i) - 'a'].add(i);
50+
}
51+
int ans = words.length;
52+
for(String word: words){
53+
int index = -1;
54+
for(int i = 0; i < word.length(); i++){
55+
char c = word.charAt(i);
56+
if(list[c - 'a'].isEmpty() || index >= list[c - 'a'].get(list[c - 'a'].size() - 1)){
57+
ans--;
58+
break;
59+
}
60+
int left = 0, right = list[c - 'a'].size();
61+
while(left < right){
62+
int mid = (left + right) >>> 1;
63+
if(list[c - 'a'].get(mid) > index) right = mid;
64+
else left = mid + 1;
65+
}
66+
index = list[c - 'a'].get(left);
67+
}
68+
}
69+
return ans;
70+
}
71+
}
72+
```
73+
74+
---
75+
76+
#### 补充
77+
78+
[寻找左右边界](https://github.com/CompetitiveLin/Leetcode/blob/61cb8c9c65c1e2f1784aaab92fb95ee78c67eea7/Dichotomy/704.%20%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.md#%E8%A1%A5%E5%85%85)类似,下面两部分展示的是求小于 `target` 的最大下标以及大于 `target ` 的最小下标。
79+
80+
**寻找最大下标**
81+
82+
在一个升序数组(数组内数字可重复)中,求小于 `target` 的最大下标,返回值的范围为 `[-1, arrays.length - 1]`
83+
84+
`-1` 代表数组内的所有数都比 `target` 大,`arrays.length - 1` 代表数组内所有数都比 `target` 小。
85+
86+
```java
87+
/**
88+
*
89+
* @param arrays
90+
* @param left = 0
91+
* @param right = arrays.length
92+
* @param target
93+
* @return
94+
*/
95+
public static int rightmost_before(int[] arrays, int left, int right, int target){
96+
while(left < right){
97+
int mid = left + (right - left) / 2;
98+
if(target > arrays[mid]){
99+
left = mid + 1;
100+
} else right = mid;
101+
}
102+
return left - 1;
103+
}
104+
```
105+
106+
**寻找最小下标**
107+
108+
在一个升序数组(数组内数字可重复)中,大于 `target` 的最小下标,返回值的范围为 `[0, arrays.length]`
109+
110+
`0` 代表数组内的所有数都比 `target` 大,`arrays.length` 代表数组内所有数都比 `target` 小。
111+
112+
```java
113+
/**
114+
*
115+
* @param arrays
116+
* @param left = 0
117+
* @param right = arrays.length
118+
* @param target
119+
* @return
120+
*/
121+
public static int leftmost_after(int[] arrays, int left, int right, int target){
122+
while(left < right){
123+
int mid = left + (right - left) / 2;
124+
if(target < arrays[mid]){
125+
right = mid;
126+
} else left = mid + 1;
127+
}
128+
return left;
129+
}
130+
```
131+

0 commit comments

Comments
 (0)