Skip to content

Commit 6ccbd4b

Browse files
Merge pull request SharingSource#753 from SharingSource/ac_oier
✨feat: add 809
2 parents 571c4d0 + f2459c7 commit 6ccbd4b

File tree

3 files changed

+133
-0
lines changed

3 files changed

+133
-0
lines changed

Index/双指针.md

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
| [719. 找出第 K 小的数对距离](https://leetcode.cn/problems/find-k-th-smallest-pair-distance/) | [LeetCode 题解链接](https://leetcode.cn/problems/find-k-th-smallest-pair-distance/solution/by-ac_oier-o4if/) | 困难 | 🤩🤩🤩🤩 |
3939
| [777. 在LR字符串中交换相邻字符](https://leetcode.cn/problems/swap-adjacent-in-lr-string/) | [LeetCode 题解链接](https://leetcode.cn/problems/swap-adjacent-in-lr-string/solution/by-ac_oier-ye71/) | 中等 | 🤩🤩🤩🤩 |
4040
| [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/) | 中等 | 🤩🤩🤩 |
41+
| [809. 情感丰富的文字](https://leetcode.cn/problems/expressive-words/) | [LeetCode 题解链接](https://leetcode.cn/problems/expressive-words/solution/by-ac_oier-tb57/) | 中等 | 🤩🤩🤩🤩🤩 |
4142
| [825. 适龄的朋友](https://leetcode-cn.com/problems/friends-of-appropriate-ages/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/friends-of-appropriate-ages/solution/gong-shui-san-xie-yi-ti-shuang-jie-pai-x-maa8/) | 中等 | 🤩🤩🤩🤩 |
4243
| [832. 翻转图像](https://leetcode-cn.com/problems/flipping-an-image/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/flipping-an-image/solution/shuang-zhi-zhen-yi-bian-chu-li-huan-you-ik0v1/) | 简单 | 🤩🤩 |
4344
| [838. 推多米诺](https://leetcode-cn.com/problems/push-dominoes/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/push-dominoes/solution/gong-shui-san-xie-yi-ti-shuang-jie-bfs-y-z52w/) | 中等 | 🤩🤩🤩🤩 |

Index/模拟.md

+1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
| [796. 旋转字符串](https://leetcode-cn.com/problems/rotate-string/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/rotate-string/solution/by-ac_oier-bnkx/) | 简单 | 🤩🤩🤩 |
111111
| [804. 唯一摩尔斯密码词](https://leetcode-cn.com/problems/unique-morse-code-words/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/unique-morse-code-words/solution/by-ac_oier-a9hv/) | 简单 | 🤩🤩🤩 |
112112
| [806. 写字符串需要的行数](https://leetcode-cn.com/problems/number-of-lines-to-write-string/) | [LeetCode 题解链接](https://leetcode-cn.com/problems/number-of-lines-to-write-string/solution/by-ac_oier-5hg2/) | 简单 | 🤩🤩🤩🤩 |
113+
| [809. 情感丰富的文字](https://leetcode.cn/problems/expressive-words/) | [LeetCode 题解链接](https://leetcode.cn/problems/expressive-words/solution/by-ac_oier-tb57/) | 中等 | 🤩🤩🤩🤩 |
113114
| [811. 子域名访问计数](https://leetcode.cn/problems/subdomain-visit-count/) | [LeetCode 题解链接](https://leetcode.cn/problems/subdomain-visit-count/solution/by-ac_oier-aex6/) | 中等 | 🤩🤩🤩🤩 |
114115
| [812. 最大三角形面积](https://leetcode.cn/problems/largest-triangle-area/) | [LeetCode 题解链接](https://leetcode.cn/problems/largest-triangle-area/solution/by-ac_oier-htv8/) | 简单 | 🤩🤩🤩🤩 |
115116
| [816. 模糊坐标](https://leetcode.cn/problems/ambiguous-coordinates/) | [LeetCode 题解链接](https://leetcode.cn/problems/ambiguous-coordinates/solution/by-ac_oier-sbxl/) | 中等 | 🤩🤩🤩🤩 |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
### 题目描述
2+
3+
这是 LeetCode 上的 **[809. 情感丰富的文字](https://leetcode.cn/problems/expressive-words/solution/by-ac_oier-tb57/)** ,难度为 **中等**
4+
5+
Tag : 「双指针」、「模拟」
6+
7+
8+
9+
有时候人们会用重复写一些字母来表示额外的感受,比如 `"hello" -> "heeellooo", "hi" -> "hiii"`。我们将相邻字母都相同的一串字符定义为相同字母组,例如:`"h", "eee", "ll", "ooo"`
10+
11+
对于一个给定的字符串 `S` ,如果另一个单词能够通过将一些字母组扩张从而使其和 `S` 相同,我们将这个单词定义为可扩张的(`stretchy`)。扩张操作定义如下:选择一个字母组(包含字母 `c` ),然后往其中添加相同的字母 `c` 使其长度达到 `3` 或以上。
12+
13+
例如,以 `"hello"` 为例,我们可以对字母组 `"o"` 扩张得到 `"hellooo"`,但是无法以同样的方法得到 `"helloo"` 因为字母组 `"oo"` 长度小于 `3`。此外,我们可以进行另一种扩张 `"ll" -> "lllll"` 以获得 `"helllllooo"`。如果 `S = "helllllooo"`,那么查询词 `"hello"` 是可扩张的,因为可以对它执行这两种扩张操作使得 `query = "hello" -> "hellooo" -> "helllllooo" = S`
14+
15+
输入一组查询单词,输出其中可扩张的单词数量。
16+
17+
示例:
18+
```
19+
输入:
20+
S = "heeellooo"
21+
words = ["hello", "hi", "helo"]
22+
23+
输出:1
24+
25+
解释:
26+
我们能通过扩张 "hello" 的 "e" 和 "o" 来得到 "heeellooo"。
27+
我们不能通过扩张 "helo" 来得到 "heeellooo" 因为 "ll" 的长度小于 3 。
28+
```
29+
30+
提示:
31+
* $0 <= len(S) <= 100$
32+
* $0 <= len(words) <= 100$
33+
* $0 <= len(words[i]) <= 100$
34+
* `S` 和所有在 `words` 中的单词都只由小写字母组成。
35+
36+
---
37+
38+
### 双指针
39+
40+
该题最难的部分就是理解 “扩张” 操作:假设有两个字符相同的连续段 `a``b`,如何判断 `a` 是否能由 `b` 扩张而来。
41+
42+
忘记掉题目所说的规则,我们重新定义 “扩张” 操作:
43+
44+
*`a``b` 长度相同,定义为可扩张;
45+
*`a``b` 长度不同,根据「`a``b` 长度对比」以及「`a` 的长度大小」分情况讨论:
46+
*`b` 长度大于 `a`,不可扩张;
47+
*`a` 长度大于 `b`**我们不一定要拿整一段的 `b` 进行扩张,可以拿 `b` 中的一个字符进行扩张。** 因此只需要满足扩张后的长度(`a` 的长度)大于 $3$ 即可定义为可扩张。
48+
49+
搞明白何为 “扩张” 后,剩余的则是简单的「双指针 + 模拟」做法。
50+
51+
Java 代码:
52+
```Java
53+
class Solution {
54+
public int expressiveWords(String s, String[] words) {
55+
int n = s.length(), ans = 0;
56+
out:for (String word : words) {
57+
int m = word.length(), i = 0, j = 0;
58+
while (i < n && j < m) {
59+
if (s.charAt(i) != word.charAt(j)) continue out;
60+
int a = i, b = j;
61+
while (a < n && s.charAt(a) == s.charAt(i)) a++;
62+
while (b < m && word.charAt(b) == word.charAt(j)) b++;
63+
a -= i; b -= j;
64+
if (a != b && (b > a || a < 3)) continue out;
65+
i += a; j += b;
66+
}
67+
if (i == n && j == m) ans++;
68+
}
69+
return ans;
70+
}
71+
}
72+
```
73+
TypeScript 代码:
74+
```TypeScript
75+
function expressiveWords(s: string, words: string[]): number {
76+
let n = s.length, ans = 0
77+
out:for (const word of words) {
78+
let m = word.length, i = 0, j = 0
79+
while (i < n && j < m) {
80+
if (s[i] != word[j]) continue out
81+
let a = i, b = j
82+
while (a < n && s[a] == s[i]) a++
83+
while (b < m && word[b] == word[j]) b++
84+
a -= i; b -= j;
85+
if (a != b && (b > a || a < 3)) continue out
86+
i += a; j += b;
87+
}
88+
if (i == n && j == m) ans++;
89+
}
90+
return ans
91+
}
92+
```
93+
Python 代码:
94+
```Python
95+
class Solution:
96+
def expressiveWords(self, s: str, words: List[str]) -> int:
97+
n, ans = len(s), 0
98+
for word in words:
99+
m, i, j = len(word), 0, 0
100+
ok = True
101+
while ok and i < n and j < m:
102+
if s[i] != word[j]:
103+
ok = False
104+
a, b = i, j
105+
while a < n and s[a] == s[i]:
106+
a += 1
107+
while b < m and word[b] == word[j]:
108+
b += 1
109+
a, b = a - i, b - j
110+
if a != b and (b > a or a < 3):
111+
ok = False
112+
i, j = i + a, j + b
113+
if ok and i == n and j == m:
114+
ans += 1
115+
return ans
116+
```
117+
* 时间复杂度:$O(n \times m + \sum_{i = 0}^{m - 1}words[i].length)$,其中 `n` 为字符串 `s` 的长度,`m` 为数组 `words` 的长度
118+
* 空间复杂度:$O(1)$
119+
120+
---
121+
122+
### 最后
123+
124+
这是我们「刷穿 LeetCode」系列文章的第 `No.809` 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先把所有不带锁的题目刷完。
125+
126+
在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。
127+
128+
为了方便各位同学能够电脑上进行调试和提交代码,我建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode
129+
130+
在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和其他优选题解。
131+

0 commit comments

Comments
 (0)