[LeetCode By Go 108]438. Find All Anagrams in a String
제목.
Given a string s and a non-empty string p, find all the start indices of p's anagrams in s.
Strings consists of lowercase English letters only and the length of both strings s and p will not be larger than 20,100.
The order of output does not matter.
Example 1:
Input: s: "cbaebabacd" p: "abc" Output: [0, 6] Explanation: The substring with start index = 0 is "cba", which is an anagram of "abc". The substring with start index = 6 is "bac", which is an anagram of "abc".
Example 2:
Input: s: "abab" p: "ab" Output: [0, 1, 2] Explanation: The substring with start index = 0 is "ab", which is an anagram of "ab". The substring with start index = 1 is "ba", which is an anagram of "ab". The substring with start index = 2 is "ab", which is an anagram of "ab".
문제 풀이 의 사고 방향.
s 에서 모든 p 의 anagrams 시작 위 치 를 찾 습 니 다.
해법
비교적 거 친 해법 은 s 를 옮 겨 다 니 며 s 에서 p 와 같은 긴 하위 문자열 s1 을 캡 처 한 다음 에 s1 과 p 가 anagrams 인지 비교 하 는 것 이다.s1 을 캡 처 하려 면 s 를 옮 겨 다 녀 야 합 니 다. 매번 캡 처 와 p 등 긴 하위 문자열 s1, 시간 복잡 도 O (n - p + 1) p = O (np) 는 anagrams 가 s1 과 p 를 비교 하 는 지 여 부 를 판단 하 는 것 은 각 문자 가 나타 난 횟수 가 같 는 지 비교 하 는 것 입 니 다. s1 각 문자 가 나타 난 횟수 를 map 에 넣 고 p 를 옮 겨 다 녀 야 합 니 다. 만약 p 에 문자 가 map 에 나타 나 지 않 았 다 면 anagrams 가 아니 라 는 것 을 설명 합 니 다.만약 에 나타 나 면 map 에서 문자 의 값 을 1 로 줄 이 고 map 의 각 값 이 0 인지 아 닌 지 를 최종 적 으로 판단 합 니 다. 0 이 아 닌 것 이 있 으 면 anagrams 가 아니 라 anagrams 임 을 설명 합 니 다. 그렇지 않 으 면 anagrams 입 니 다.시간 복잡 도 는 O (p + p) = O (p) 이다.총 시간 복잡 도 O (n * p2) 와 같은 해법 은 시간 초과 로 이 어 질 수 있다.
해법
s1 에 p - 2 개의 수가 겹 치 는 것 을 감안 하여 s1 이 뒤로 이동 할 때 뒤의 문자 가 나타 나 는 횟수 를 늘 리 고 앞의 문자 가 나타 나 는 횟수 를 줄 이 며 p 의 문 자 를 pMap 에 넣 을 수 있 습 니 다. sMap 에 나타 난 문 자 를 만나면 문자 가 나타 나 는 개 수 를 직접 판단 할 수 있 습 니 다. 횟수 가 다 르 면 anagrams 가 아 닙 니 다.같 으 면 sMap 의 대응 치 를 0 으로 설정 합 니 다. 옮 겨 다 닌 후 모든 sMap 의 값 이 0 이면 anagrams 입 니 다. 그렇지 않 으 면 anagrams 가 아 닙 니 다.시간 복잡 도 O (1) 총 시간 복잡 도 O (n)
코드
findAnagrams.go
package _438_Find_All_Anagrams_in_a_String
import "fmt"
func FindAnagrams(s string, p string) []int {
lenP := len(p)
var ret []int
lenS := len(s)
if lenS < lenP {
return []int{}
}
var charMap map[byte]int
charMap = make(map[byte]int)
for i := 0; i < lenP; i++ {
charMap[p[i]]++
}
var sMap map[byte]int
sMap = make(map[byte]int)
for i := 0; i < lenP; i++ {
sMap[s[i]]++
}
for i := 0; i < lenS - lenP + 1; i++ {
fmt.Printf("%+v
", s[i:i+lenP])
isAnagrams := true
var tmpMap map[byte]int
tmpMap = make(map[byte]int)
for k, v := range charMap {
tmpMap[k] = v
}
if i > 0 {
sMap[s[i+lenP-1]]++
sMap[s[i-1]]--
}
for k, v := range sMap {
if 0 == v {
continue
}
_, ok := tmpMap[k]
if !ok {
isAnagrams = false
break
}
tmpMap[k] -= v
}
if isAnagrams {
for _, v := range tmpMap {
if v > 0 {
isAnagrams = false
break
}
}
}
if isAnagrams {
ret = append(ret, i)
}
}
return ret
}
테스트
findAnagrams_test.go
package _438_Find_All_Anagrams_in_a_String
import "testing"
func equalSlice(s, p []int) bool {
len1 := len(s)
len2 := len(p)
if len1 != len2 {
return false
}
for i := 0; i < len1; i++ {
if s[i] != p[i] {
return false
}
}
return true
}
func TestFindAnagrams(t *testing.T) {
var tests = []struct{
s string
p string
ret []int
} {
{"cbaebabacd", "abc", []int{0,6}},
{"baa", "aa", []int{1}},
}
for _, v := range tests {
ret := FindAnagrams(v.s, v.p)
if equalSlice(ret, v.ret) {
t.Logf("pass")
} else {
t.Errorf("fail, want %+v, get %+v", v.ret, ret)
}
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.