Skip to content

Commit 010082e

Browse files
committed
0567.Permutation-in-String
1 parent 1887512 commit 010082e

File tree

4 files changed

+272
-0
lines changed

4 files changed

+272
-0
lines changed
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# [567. Permutation in String](https://leetcode.com/problems/permutation-in-string/)
2+
###### tags: `Medium` `Leetcode` `Sliding Window`
3+
4+
## 題目
5+
Given two strings s1 and s2, return true if s2 contains a permutation of s1, or false otherwise.
6+
7+
In other words, return true if one of s1's permutations is the substring of s2.
8+
9+
10+
Example 1:
11+
```
12+
Input: s1 = "ab", s2 = "eidbaooo"
13+
Output: true
14+
Explanation: s2 contains one permutation of s1 ("ba").
15+
```
16+
17+
Example 2:
18+
19+
Input: s1 = "ab", s2 = "eidboaoo"
20+
Output: false
21+
22+
23+
Constraints:
24+
25+
* 1 <= s1.length, s2.length <= 104
26+
* s1 and s2 consist of lowercase English letters.
27+
28+
## 題目大意
29+
輸入兩個String S1 和 S2 , 判斷 S2 是否包含S1的排列, 也就是要判斷 S2 中是否存在一個子字串是S1的一種全排列
30+
31+
## 解題思路
32+
Sliding Window
33+
可以用 slice 取代 map 來優化
34+
35+
## 來源
36+
* https://leetcode.com/problems/permutation-in-string/
37+
38+
## 解答
39+
https://github.com/kimi0230/LeetcodeGolang/blob/master/Leetcode/0567.Permutation-in-String/main.go
40+
41+
```go
42+
package permutationinstring
43+
44+
func CheckInclusion(s1 string, s2 string) bool {
45+
need, window := make(map[rune]int), make(map[rune]int)
46+
for _, c := range s1 {
47+
need[c]++
48+
}
49+
50+
left, right := 0, 0
51+
valid := 0
52+
for right < len(s2) {
53+
c := rune(s2[right])
54+
right++
55+
56+
// 進行窗口內數據的一系列更新
57+
if need[c] > 0 {
58+
window[c]++
59+
if window[c] == need[c] {
60+
// 該字符長度達到
61+
valid++
62+
}
63+
}
64+
65+
// fmt.Printf("[%d,%d) \n", left, right)
66+
67+
// 判斷左視窗是否要收縮
68+
// for (right - left) >= len(s1)
69+
if (right - left) >= len(s1) {
70+
71+
if valid == len(need) {
72+
// 全找到
73+
return true
74+
}
75+
d := rune(s2[left])
76+
left++
77+
if need[d] > 0 {
78+
if window[d] == need[d] {
79+
valid--
80+
}
81+
window[d]--
82+
}
83+
}
84+
}
85+
return false
86+
}
87+
88+
// 用 slice 取代 map 來優化
89+
func CheckInclusionSlice(s1 string, s2 string) bool {
90+
need := [256]int{}
91+
for _, c := range s1 {
92+
need[c-'a']++
93+
}
94+
95+
left, right := 0, 0
96+
count := len(s1)
97+
for right < len(s2) {
98+
c := s2[right] - 'a'
99+
100+
if need[c] > 0 {
101+
// 有找到
102+
count--
103+
}
104+
need[c]--
105+
right++
106+
107+
// fmt.Printf("[%d,%d)\n", left, right)
108+
if count == 0 {
109+
return true
110+
}
111+
112+
// 判斷左視窗是否要收縮
113+
if (right - left) == len(s1) {
114+
d := s2[left] - 'a'
115+
if need[d] >= 0 {
116+
// 符合預期的長度, 但是卻沒找到預期的結果
117+
count++
118+
}
119+
need[d]++
120+
left++
121+
}
122+
}
123+
return false
124+
}
125+
```
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package permutationinstring
2+
3+
func CheckInclusion(s1 string, s2 string) bool {
4+
need, window := make(map[rune]int), make(map[rune]int)
5+
for _, c := range s1 {
6+
need[c]++
7+
}
8+
9+
left, right := 0, 0
10+
valid := 0
11+
for right < len(s2) {
12+
c := rune(s2[right])
13+
right++
14+
15+
// 進行窗口內數據的一系列更新
16+
if need[c] > 0 {
17+
window[c]++
18+
if window[c] == need[c] {
19+
// 該字符長度達到
20+
valid++
21+
}
22+
}
23+
24+
// fmt.Printf("[%d,%d) \n", left, right)
25+
26+
// 判斷左視窗是否要收縮
27+
// for (right - left) >= len(s1)
28+
if (right - left) >= len(s1) {
29+
30+
if valid == len(need) {
31+
// 全找到
32+
return true
33+
}
34+
d := rune(s2[left])
35+
left++
36+
if need[d] > 0 {
37+
if window[d] == need[d] {
38+
valid--
39+
}
40+
window[d]--
41+
}
42+
}
43+
}
44+
return false
45+
}
46+
47+
// 用 slice 取代 map 來優化
48+
func CheckInclusionSlice(s1 string, s2 string) bool {
49+
need := [256]int{}
50+
for _, c := range s1 {
51+
need[c-'a']++
52+
}
53+
54+
left, right := 0, 0
55+
count := len(s1)
56+
for right < len(s2) {
57+
c := s2[right] - 'a'
58+
59+
if need[c] > 0 {
60+
// 有找到
61+
count--
62+
}
63+
need[c]--
64+
right++
65+
66+
// fmt.Printf("[%d,%d)\n", left, right)
67+
if count == 0 {
68+
return true
69+
}
70+
71+
// 判斷左視窗是否要收縮
72+
if (right - left) == len(s1) {
73+
d := s2[left] - 'a'
74+
if need[d] >= 0 {
75+
// 符合預期的長度, 但是卻沒找到預期的結果
76+
count++
77+
}
78+
need[d]++
79+
left++
80+
}
81+
}
82+
return false
83+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package permutationinstring
2+
3+
import "testing"
4+
5+
var tests = []struct {
6+
arg1 string
7+
arg2 string
8+
want bool
9+
}{
10+
{
11+
"ab",
12+
"eidbaooo",
13+
true,
14+
},
15+
{
16+
"ab",
17+
"eidboaoo",
18+
false,
19+
},
20+
}
21+
22+
func TestCheckInclusion(t *testing.T) {
23+
for _, tt := range tests {
24+
if got := CheckInclusion(tt.arg1, tt.arg2); got != tt.want {
25+
t.Errorf("got = %v, want = %v", got, tt.want)
26+
}
27+
}
28+
}
29+
30+
func TestCheckInclusionSlice(t *testing.T) {
31+
for _, tt := range tests {
32+
if got := CheckInclusionSlice(tt.arg1, tt.arg2); got != tt.want {
33+
t.Errorf("got = %v, want = %v", got, tt.want)
34+
}
35+
}
36+
}
37+
38+
func BenchmarkCheckInclusion(b *testing.B) {
39+
b.ResetTimer()
40+
for i := 0; i < b.N; i++ {
41+
CheckInclusion(tests[0].arg1, tests[0].arg2)
42+
}
43+
}
44+
45+
func BenchmarkCheckInclusionSlice(b *testing.B) {
46+
b.ResetTimer()
47+
for i := 0; i < b.N; i++ {
48+
CheckInclusionSlice(tests[0].arg1, tests[0].arg2)
49+
}
50+
}
51+
52+
/*
53+
go test -benchmem -run=none LeetcodeGolang/Leetcode/0567.Permutation-in-String -bench=.
54+
goos: darwin
55+
goarch: amd64
56+
pkg: LeetcodeGolang/Leetcode/0567.Permutation-in-String
57+
cpu: Intel(R) Core(TM) i5-8259U CPU @ 2.30GHz
58+
BenchmarkCheckInclusion-8 9091321 167.9 ns/op 0 B/op 0 allocs/op
59+
BenchmarkCheckInclusionSlice-8 26744336 53.28 ns/op 0 B/op 0 allocs/op
60+
PASS
61+
ok LeetcodeGolang/Leetcode/0567.Permutation-in-String 3.143s
62+
*/

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ void slidingWindow(string s, string t){
133133
int left = 0 , right = 0
134134
int valid = 0
135135

136+
// 先移動 right 再移動 left. 直到right到達 string的末端
136137
while(right < s.size()){
137138
// c是將移入窗口的字符
138139
char c = s[right]
@@ -159,6 +160,7 @@ void slidingWindow(string s, string t){
159160
| No. | Title | Solution | Difficulty | Time | Space | Topic |
160161
|-----|:-----:|:--------:|------------|------|-------|-------|
161162
| 0209 | [Minimum Size Subarray Sum](https://leetcode.com/problems/minimum-size-subarray-sum/) | [Go](https://github.com/kimi0230/LeetcodeGolang/tree/master/Leetcode/0209.Minimum-Size-Subarray-Sum) | Medium | O(n^2) / O(n) / O(nlog n) | O(1) / O(1) / O(n) | Sliding Window |
163+
| 0567 | [Permutation in String](https://leetcode.com/problems/permutation-in-string/) | [Go](https://github.com/kimi0230/LeetcodeGolang/tree/master/Leetcode/0567.Permutation-in-String) | Medium | O(n) | O(1) | Sliding Window |
162164

163165
---
164166

0 commit comments

Comments
 (0)