Skip to content

Commit e030d3e

Browse files
committed
feat: add solutions to lc problem: No.0567
No.0567.Permutation in String
1 parent 94b6982 commit e030d3e

File tree

6 files changed

+687
-92
lines changed

6 files changed

+687
-92
lines changed

solution/0500-0599/0567.Permutation in String/README.md

Lines changed: 278 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,22 @@
4040

4141
<!-- 这里可写通用的实现逻辑 -->
4242

43+
**方法一:滑动窗口**
44+
45+
我们观察发现,题目实际上等价于判断字符串 $s2$ 中是否存在窗口大小为 $n$,且窗口内的字符及其个数与字符串 $s1$ 相同的子串。
46+
47+
因此,我们先用哈希表或数组 $cnt1$ 统计字符串 $s1$ 中每个字符出现的次数,然后遍历字符串 $s2$,维护一个窗口大小为 $n$ 的滑动窗口,用哈希表或数组 $cnt2$ 统计窗口内每个字符出现的次数,当 $cnt1 = cnt2$ 时,说明窗口内的字符及其个数与字符串 $s1$ 相同,返回 `true` 即可。
48+
49+
否则,遍历结束后,返回 `false`
50+
51+
时间复杂度 $(n + m \times C)$,空间复杂度 $O(C)$。其中 $n$ 和 $m$ 分别为字符串 $s1$ 和 $s2$ 的长度;而 $C$ 为字符集的大小,本题中 $C=26$。
52+
53+
**方法二:滑动窗口优化**
54+
55+
在方法一中,我们每次加入和移除一个字符时,都需要比较两个哈希表或数组,时间复杂度较高。我们可以维护一个变量 $diff$,表示两个大小为 $n$ 的字符串中,有多少种字符出现的个数不同。当 $diff=0$ 时,说明两个字符串中的字符个数相同。
56+
57+
时间复杂度 $O(n + m)$,空间复杂度 $O(C)$。其中 $n$ 和 $m$ 分别为字符串 $s1$ 和 $s2$ 的长度;而 $C$ 为字符集的大小,本题中 $C=26$。
58+
4359
<!-- tabs:start -->
4460

4561
### **Python3**
@@ -49,30 +65,49 @@
4965
```python
5066
class Solution:
5167
def checkInclusion(self, s1: str, s2: str) -> bool:
52-
need, window = {}, {}
53-
validate, left, right = 0, 0, 0
54-
for c in s1:
55-
window[c] = 0
56-
if c in need:
57-
need[c] += 1
58-
else:
59-
need[c] = 1
60-
61-
for right in range(len(s2)):
62-
c = s2[right]
63-
if c in need:
64-
window[c] += 1
65-
if window[c] == need[c]:
66-
validate += 1
67-
while right - left + 1 >= len(s1):
68-
if validate == len(need):
69-
return True
70-
d = s2[left]
71-
left += 1
72-
if d in need:
73-
if window[d] == need[d]:
74-
validate -= 1
75-
window[d] -= 1
68+
n = len(s1)
69+
cnt1 = Counter(s1)
70+
cnt2 = Counter(s2[:n])
71+
if cnt1 == cnt2:
72+
return True
73+
for i in range(n, len(s2)):
74+
cnt2[s2[i]] += 1
75+
cnt2[s2[i - n]] -= 1
76+
if cnt1 == cnt2:
77+
return True
78+
return False
79+
```
80+
81+
```python
82+
class Solution:
83+
def checkInclusion(self, s1: str, s2: str) -> bool:
84+
n, m = len(s1), len(s2)
85+
if n > m:
86+
return False
87+
cnt = Counter()
88+
for a, b in zip(s1, s2):
89+
cnt[a] -= 1
90+
cnt[b] += 1
91+
diff = sum(x != 0 for x in cnt.values())
92+
if diff == 0:
93+
return True
94+
for i in range(n, m):
95+
a, b = s2[i - n], s2[i]
96+
97+
if cnt[b] == 0:
98+
diff += 1
99+
cnt[b] += 1
100+
if cnt[b] == 0:
101+
diff -= 1
102+
103+
if cnt[a] == 0:
104+
diff += 1
105+
cnt[a] -= 1
106+
if cnt[a] == 0:
107+
diff -= 1
108+
109+
if diff == 0:
110+
return True
76111
return False
77112
```
78113

@@ -81,7 +116,226 @@ class Solution:
81116
<!-- 这里可写当前语言的特殊实现逻辑 -->
82117

83118
```java
119+
class Solution {
120+
public boolean checkInclusion(String s1, String s2) {
121+
int n = s1.length();
122+
int m = s2.length();
123+
if (n > m) {
124+
return false;
125+
}
126+
int[] cnt1 = new int[26];
127+
int[] cnt2 = new int[26];
128+
for (int i = 0; i < n; ++i) {
129+
++cnt1[s1.charAt(i) - 'a'];
130+
++cnt2[s2.charAt(i) - 'a'];
131+
}
132+
if (Arrays.equals(cnt1, cnt2)) {
133+
return true;
134+
}
135+
for (int i = n; i < m; ++i) {
136+
++cnt2[s2.charAt(i) - 'a'];
137+
--cnt2[s2.charAt(i - n) - 'a'];
138+
if (Arrays.equals(cnt1, cnt2)) {
139+
return true;
140+
}
141+
}
142+
return false;
143+
}
144+
}
145+
```
146+
147+
```java
148+
class Solution {
149+
public boolean checkInclusion(String s1, String s2) {
150+
int n = s1.length();
151+
int m = s2.length();
152+
if (n > m) {
153+
return false;
154+
}
155+
int[] cnt = new int[26];
156+
for (int i = 0; i < n; ++i) {
157+
--cnt[s1.charAt(i) - 'a'];
158+
++cnt[s2.charAt(i) - 'a'];
159+
}
160+
int diff = 0;
161+
for (int x : cnt) {
162+
if (x != 0) {
163+
++diff;
164+
}
165+
}
166+
if (diff == 0) {
167+
return true;
168+
}
169+
for (int i = n; i < m; ++i) {
170+
int a = s2.charAt(i - n) - 'a';
171+
int b = s2.charAt(i) - 'a';
172+
if (cnt[b] == 0) {
173+
++diff;
174+
}
175+
if (++cnt[b] == 0) {
176+
--diff;
177+
}
178+
if (cnt[a] == 0) {
179+
++diff;
180+
}
181+
if (--cnt[a] == 0) {
182+
--diff;
183+
}
184+
if (diff == 0) {
185+
return true;
186+
}
187+
}
188+
return false;
189+
}
190+
}
191+
```
192+
193+
### **C++**
84194

195+
```cpp
196+
class Solution {
197+
public:
198+
bool checkInclusion(string s1, string s2) {
199+
int n = s1.size(), m = s2.size();
200+
if (n > m) {
201+
return false;
202+
}
203+
vector<int> cnt1(26), cnt2(26);
204+
for (int i = 0; i < n; ++i) {
205+
++cnt1[s1[i] - 'a'];
206+
++cnt2[s2[i] - 'a'];
207+
}
208+
if (cnt1 == cnt2) {
209+
return true;
210+
}
211+
for (int i = n; i < m; ++i) {
212+
++cnt2[s2[i] - 'a'];
213+
--cnt2[s2[i - n] - 'a'];
214+
if (cnt1 == cnt2) {
215+
return true;
216+
}
217+
}
218+
return false;
219+
}
220+
};
221+
```
222+
223+
```cpp
224+
class Solution {
225+
public:
226+
bool checkInclusion(string s1, string s2) {
227+
int n = s1.size(), m = s2.size();
228+
if (n > m) {
229+
return false;
230+
}
231+
vector<int> cnt(26);
232+
for (int i = 0; i < n; ++i) {
233+
--cnt[s1[i] - 'a'];
234+
++cnt[s2[i] - 'a'];
235+
}
236+
int diff = 0;
237+
for (int x : cnt) {
238+
if (x) {
239+
++diff;
240+
}
241+
}
242+
if (diff == 0) {
243+
return true;
244+
}
245+
for (int i = n; i < m; ++i) {
246+
int a = s2[i - n] - 'a';
247+
int b = s2[i] - 'a';
248+
if (cnt[b] == 0) {
249+
++diff;
250+
}
251+
if (++cnt[b] == 0) {
252+
--diff;
253+
}
254+
if (cnt[a] == 0) {
255+
++diff;
256+
}
257+
if (--cnt[a] == 0) {
258+
--diff;
259+
}
260+
if (diff == 0) {
261+
return true;
262+
}
263+
}
264+
return false;
265+
}
266+
};
267+
```
268+
269+
### **Go**
270+
271+
```go
272+
func checkInclusion(s1 string, s2 string) bool {
273+
n, m := len(s1), len(s2)
274+
if n > m {
275+
return false
276+
}
277+
cnt1 := [26]int{}
278+
cnt2 := [26]int{}
279+
for i := range s1 {
280+
cnt1[s1[i]-'a']++
281+
cnt2[s2[i]-'a']++
282+
}
283+
if cnt1 == cnt2 {
284+
return true
285+
}
286+
for i := n; i < m; i++ {
287+
cnt2[s2[i]-'a']++
288+
cnt2[s2[i-n]-'a']--
289+
if cnt1 == cnt2 {
290+
return true
291+
}
292+
}
293+
return false
294+
}
295+
```
296+
297+
```go
298+
func checkInclusion(s1 string, s2 string) bool {
299+
n, m := len(s1), len(s2)
300+
if n > m {
301+
return false
302+
}
303+
cnt := [26]int{}
304+
for i := range s1 {
305+
cnt[s1[i]-'a']--
306+
cnt[s2[i]-'a']++
307+
}
308+
diff := 0
309+
for _, x := range cnt {
310+
if x != 0 {
311+
diff++
312+
}
313+
}
314+
if diff == 0 {
315+
return true
316+
}
317+
for i := n; i < m; i++ {
318+
a, b := s2[i-n]-'a', s2[i]-'a'
319+
if cnt[b] == 0 {
320+
diff++
321+
}
322+
cnt[b]++
323+
if cnt[b] == 0 {
324+
diff--
325+
}
326+
if cnt[a] == 0 {
327+
diff++
328+
}
329+
cnt[a]--
330+
if cnt[a] == 0 {
331+
diff--
332+
}
333+
if diff == 0 {
334+
return true
335+
}
336+
}
337+
return false
338+
}
85339
```
86340

87341
### **TypeScript**

0 commit comments

Comments
 (0)