Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1fe9095

Browse files
Merge pull request #746 from SharingSource/ac_oier
✨feat: add 792 & 775
2 parents 9f5e068 + 06449a1 commit 1fe9095

File tree

5 files changed

+175
-9
lines changed

5 files changed

+175
-9
lines changed

‎Index/二分.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
| [744. 寻找比目标字母大的最小字母](https://leetcode-cn.com/problems/find-smallest-letter-greater-than-target/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/find-smallest-letter-greater-than-target/solution/by-ac_oier-to07/) | 简单 | 🤩🤩🤩🤩🤩 |
4444
| [778. 水位上升的泳池中游泳](https://leetcode-cn.com/problems/swim-in-rising-water/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/swim-in-rising-water/solution/gong-shui-san-xie-yi-ti-shuang-jie-krusk-7c6o/) | 困难 | 🤩🤩🤩 |
4545
| [786. 第 K 个最小的素数分数](https://leetcode-cn.com/problems/k-th-smallest-prime-fraction/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/k-th-smallest-prime-fraction/solution/gong-shui-san-xie-yi-ti-shuang-jie-you-x-8ymk/) | 中等 | 🤩🤩🤩 |
46+
| [792. 匹配子序列的单词数](https://leetcode.cn/problems/number-of-matching-subsequences/) | [LeetCode 题解链接](https://leetcode.cn/problems/number-of-matching-subsequences/solution/by-ac_oier-u1ox/) | 中等 | 🤩🤩🤩🤩 |
4647
| [793. 阶乘函数后 K 个零](https://leetcode.cn/problems/preimage-size-of-factorial-zeroes-function/) | [LeetCode 题解链接](https://leetcode.cn/problems/preimage-size-of-factorial-zeroes-function/solution/by-ac_oier-pk9g/) | 困难 | 🤩🤩🤩🤩 |
4748
| [852. 山脉数组的峰顶索引](https://leetcode-cn.com/problems/peak-index-in-a-mountain-array/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/peak-index-in-a-mountain-array/solution/gong-shui-san-xie-er-fen-san-fen-cha-zhi-5gfv/) | 简单 | 🤩🤩🤩🤩🤩 |
4849
| [875. 爱吃香蕉的珂珂](https://leetcode.cn/problems/koko-eating-bananas/) | [LeetCode 题解链接](https://leetcode.cn/problems/koko-eating-bananas/solution/by-ac_oier-4z7i/) | 中等 | 🤩🤩🤩🤩 |

‎Index/哈希表.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
| [726. 原子的数量](https://leetcode-cn.com/problems/number-of-atoms/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-atoms/solution/gong-shui-san-xie-shi-yong-xiao-ji-qiao-l5ak4/) | 困难 | 🤩🤩🤩🤩 |
4848
| [728. 自除数](https://leetcode-cn.com/problems/self-dividing-numbers/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/self-dividing-numbers/solution/by-ac_oier-pvb1/) | 简单 | 🤩🤩🤩 |
4949
| [736. Lisp 语法解析](https://leetcode.cn/problems/parse-lisp-expression/) | [LeetCode 题解链接](https://leetcode.cn/problems/parse-lisp-expression/solution/by-ac_oier-i7w1/) | 困难 | 🤩🤩🤩🤩 |
50+
| [792. 匹配子序列的单词数](https://leetcode.cn/problems/number-of-matching-subsequences/) | [LeetCode 题解链接](https://leetcode.cn/problems/number-of-matching-subsequences/solution/by-ac_oier-u1ox/) | 中等 | 🤩🤩🤩🤩 |
5051
| [811. 子域名访问计数](https://leetcode.cn/problems/subdomain-visit-count/) | [LeetCode 题解链接](https://leetcode.cn/problems/subdomain-visit-count/solution/by-ac_oier-aex6/) | 中等 | 🤩🤩🤩🤩 |
5152
| [817. 链表组件](https://leetcode.cn/problems/linked-list-components/) | [LeetCode 题解链接](https://leetcode.cn/problems/linked-list-components/solution/by-ac_oier-3gl5/) | 中等 | 🤩🤩🤩🤩 |
5253
| [846. 一手顺子](https://leetcode-cn.com/problems/hand-of-straights/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/hand-of-straights/solution/gong-shui-san-xie-shu-ju-jie-gou-mo-ni-t-4hxw/) | 中等 | 🤩🤩🤩 |

‎LeetCode/161-170/162. 寻找峰值(中等).md‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@
44

55
Tag : 「二分」
66

7+
8+
79
峰值元素是指其值严格大于左右相邻值的元素。
810

9-
给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
11+
给你一个整数数组 `nums`,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
1012

11-
你可以假设 nums[-1] = nums[n] = -∞ 。
13+
你可以假设 `nums[-1] = nums[n] = -∞`
1214

13-
你必须实现时间复杂度为 O(log n) 的算法来解决此问题。
15+
你必须实现时间复杂度为 $O(\log{n})$ 的算法来解决此问题。
1416

1517
示例 1:
1618
```
@@ -30,11 +32,10 @@ Tag : 「二分」
3032
或者返回索引 5, 其峰值元素为 6。
3133
```
3234

33-
3435
提示:
35-
* 1 <= nums.length <= 1000
36-
* -$2^{31}$ <= nums[i] <= $2^{31}$ - 1
37-
* 对于所有有效的 i 都有 nums[i] != nums[i + 1]
36+
* $1 <= nums.length <= 1000$
37+
* $-2^{31} <= nums[i] <= 2^{31} - 1$
38+
* 对于所有有效的 `i` 都有 `nums[i] != nums[i + 1]`
3839

3940
---
4041

‎LeetCode/771-780/775. 全局倒置与局部倒置(中等).md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Tag : 「树状数组」、「数学」
88

99
给你一个长度为 `n` 的整数数组 `nums`,表示由范围 $[0, n - 1]$ 内所有整数组成的一个排列。
1010

11-
全局倒置 的数目等于满足下述条件不同下标对 (i, j) 的数目:
11+
全局倒置 的数目等于满足下述条件不同下标对 $(i, j)$ 的数目:
1212

1313
* 0ドル <= i < j < n$
1414
* $nums[i] > nums[j]$
@@ -38,7 +38,7 @@ Tag : 「树状数组」、「数学」
3838
```
3939

4040
提示:
41-
* $n == nums.length$
41+
* $n = nums.length$
4242
* 1ドル <= n <= 10^5$
4343
* 0ドル <= nums[i] < n$
4444
* `nums` 中的所有整数 互不相同
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[792. 匹配子序列的单词数](https://leetcode.cn/problems/number-of-matching-subsequences/solution/by-ac_oier-u1ox/)** ,难度为 **中等**
4+
5+
Tag : 「二分」、「哈希表」
6+
7+
8+
9+
给定字符串 `s` 和字符串数组 `words`, 返回 `words[i]` 中是 `s` 的子序列的单词个数 。
10+
11+
字符串的 子序列 是从原始字符串中生成的新字符串,可以从中删去一些字符(可以是`""`),而不改变其余字符的相对顺序。
12+
13+
例如, `"ace"``"abcde"` 的子序列。
14+
15+
示例 1:
16+
```
17+
输入: s = "abcde", words = ["a","bb","acd","ace"]
18+
19+
输出: 3
20+
21+
解释: 有三个是 s 的子序列的单词: "a", "acd", "ace"。
22+
```
23+
示例 2:
24+
```
25+
输入: s = "dsahjpjauf", words = ["ahjpjau","ja","ahbwzgqnuk","tnmlanowax"]
26+
27+
输出: 2
28+
```
29+
30+
提示:
31+
* 1ドル <= s.length <= 5 \times 10^4$
32+
* 1ドル <= words.length <= 5000$
33+
* 1ドル <= words[i].length <= 50$
34+
* `words[i]``s` 都只由小写字母组成。
35+
36+
---
37+
38+
### 预处理 + 哈希表 + 二分
39+
40+
朴素判定某个字符串是为另一字符串的子序列的复杂度为 $O(n + m),ドル对于本题共有 5000ドル$ 个字符串需要判定,每个字符串最多长为 50ドル,ドル因此整体计算量为 $(5 \times 10^4 + 50) \times 5000 \approx 2.5 \times 10^8,ドル会超时。
41+
42+
不可避免的是,我们要对每个 $words[i]$ 进行检查,因此优化的思路可放在如何优化单个 $words[i]$ 的判定操作。
43+
44+
朴素的判定过程需要使用双指针扫描两个字符串,其中对于原串的扫描,会有大量的字符会被跳过(无效匹配),即只有两指针对应的字符相同时,匹配串指针才会后移。
45+
46+
我们考虑如何优化这部分无效匹配。
47+
48+
对于任意一个 $w = words[i]$ 而言,假设我们当前匹配到 $w[j]$ 位置,此时我们已经明确下一个待匹配的字符为 $w[j + 1],ドル因此我们可以直接在 `s` 中字符为 $w[j + 1]$ 的位置中找候选。
49+
50+
具体的,我们可以使用哈希表 `map``s` 进行预处理:以字符 $c = s[i]$ 为哈希表的 `key`,对应的下标 $i$ 集合为 `value`,由于我们从前往后处理 `s` 进行预处理,因此对于所有的 `value` 均满足递增性质。
51+
52+
> 举个 🌰 : 对于 `s = abcabc` 而言,预处理的哈希表为 `{a=[0,3], b=[1,4], c=[2,5]}`
53+
54+
最后考虑如何判定某个 $w = words[i]$ 是否满足要求:待匹配字符串 `w` 长度为 `m`,我们从前往后对 `w` 进行判定,假设当前判待匹配位置为 $w[i],ドル我们使用变量 `idx` 代表能够满足匹配 $w[0:i]$ 的最小下标(贪心思路)。
55+
56+
对于匹配的 $w[i]$ 字符,可以等价为在 `map[w[i]]` 中找到第一个大于 `idx` 的下标,含义在原串 `s` 中找到字符为 `w[i]` 且下标大于 `idx` 的最小值,由于我们所有的 `map[X]` 均满足单调递增,该过程可使用「二分」进行。
57+
58+
Java 代码:
59+
```Java
60+
class Solution {
61+
public int numMatchingSubseq(String s, String[] words) {
62+
int n = s.length(), ans = 0;
63+
Map<Character, List<Integer>> map = new HashMap<>();
64+
for (int i = 0; i < n; i++) {
65+
List<Integer> list = map.getOrDefault(s.charAt(i), new ArrayList<>());
66+
list.add(i);
67+
map.put(s.charAt(i), list);
68+
}
69+
for (String w : words) {
70+
boolean ok = true;
71+
int m = w.length(), idx = -1;
72+
for (int i = 0; i < m && ok; i++) {
73+
List<Integer> list = map.getOrDefault(w.charAt(i), new ArrayList<>());
74+
int l = 0, r = list.size() - 1;
75+
while (l < r) {
76+
int mid = l + r >> 1;
77+
if (list.get(mid) > idx) r = mid;
78+
else l = mid + 1;
79+
}
80+
if (r < 0 || list.get(r) <= idx) ok = false;
81+
else idx = list.get(r);
82+
}
83+
if (ok) ans++;
84+
}
85+
return ans;
86+
}
87+
}
88+
```
89+
TypeScript 代码:
90+
```TypeScript
91+
function numMatchingSubseq(s: string, words: string[]): number {
92+
let n = s.length, ans = 0
93+
const map = new Map<String, Array<number>>()
94+
for (let i = 0; i < n; i++) {
95+
if (!map.has(s[i])) map.set(s[i], new Array<number>())
96+
map.get(s[i]).push(i)
97+
}
98+
for (const w of words) {
99+
let ok = true
100+
let m = w.length, idx = -1
101+
for (let i = 0; i < m && ok; i++) {
102+
if (!map.has(w[i])) {
103+
ok = false
104+
} else {
105+
const list = map.get(w[i])
106+
let l = 0, r = list.length - 1
107+
while (l < r) {
108+
const mid = l + r >> 1
109+
if (list[mid] > idx) r = mid
110+
else l = mid + 1
111+
}
112+
if (r < 0 || list[r] <= idx) ok = false
113+
else idx = list[r]
114+
}
115+
}
116+
if (ok) ans++
117+
}
118+
return ans
119+
}
120+
```
121+
Python3 代码:
122+
```Python3
123+
class Solution:
124+
def numMatchingSubseq(self, s: str, words: List[str]) -> int:
125+
dmap = defaultdict(list)
126+
for i, c in enumerate(s):
127+
dmap[c].append(i)
128+
ans = 0
129+
for w in words:
130+
ok = True
131+
idx = -1
132+
for i in range(len(w)):
133+
idxs = dmap[w[i]]
134+
l, r = 0, len(idxs) - 1
135+
while l < r :
136+
mid = l + r >> 1
137+
if dmap[w[i]][mid] > idx:
138+
r = mid
139+
else:
140+
l = mid + 1
141+
if r < 0 or dmap[w[i]][r] <= idx:
142+
ok = False
143+
break
144+
else:
145+
idx = dmap[w[i]][r]
146+
ans += 1 if ok else 0
147+
return ans
148+
```
149+
* 时间复杂度:令 `n``s` 长度,`m``words` 长度,`l = 50` 为 $words[i]$ 长度的最大值。构造 `map` 的复杂度为 $O(n)$;统计符合要求的 $words[i]$ 的数量复杂度为 $O(m \times l \times \log{n})$。整体复杂度为 $O(n + m \times l \times \log{n})$
150+
* 空间复杂度:$O(n)$
151+
152+
---
153+
154+
### 最后
155+
156+
这是我们「刷穿 LeetCode」系列文章的第 `No.792` 篇,系列开始于 2021年01月01日,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
157+
158+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
159+
160+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
161+
162+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
163+

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /