Algorithm
[leetcode 75] 438. Find All Anagrams in a String
BE Engineer
2023. 2. 27. 02:17

문제 해석
문자열 s와 p가 주어졌을 때 p가 s의 anagram인 위치들을 반환하기
위치들의 순서는 상관없음.
anagram이란?
모든 원래 문자를 정확히 한 번만 사용하여 재배열해 형성된 단어 또는 구
예시
"abc"의 anagram은 "cba", "abc", "bca"등을 말함
정답 예
public List<Integer> findAnagrams(String s, String p) {
List<Integer> output = new ArrayList<>();
// p의 길이
int pLength = p.length();
// s의 길이
int sLength = s.length();
if (pLength > sLength) {
return output;
}
// p의 문자 개수를 기록할 배열
int[] pLetters = new int[26];
// s의 위치에 따른 부분 문자 개수를 기록할 배열
int[] sSubletters = new int[26];
// p의 길이만큼 문자개수 기록
for (int i=0;i<pLength;i++) {
pLetters[p.charAt(i) - 'a']++;
sSubletters[s.charAt(i) - 'a']++;
}
for (int i=0;i<sLength-pLength+1;i++) {
boolean result = true;
// s의 p길이만큼의 부분 문자열이 Anagrams인지 체크
// 모든 문자의 개수가 동일하면 true
for (int j=0;j<26;j++) {
if (pLetters[j] != sSubletters[j]) {
result = false;
break;
}
}
if (result) {
output.add(i);
}
if (i<sLength-pLength) {
// 검증한 부분문자열의 처음 문자열 제거
sSubletters[s.charAt(i) - 'a']--;
// 다음에 검증할 부분문자열의 마지막 문자열만 추가
sSubletters[s.charAt(pLength + i) - 'a']++;
}
}
return output;
}
이 문제해서 시간복잡도를 줄일 수 있는 부분은 체크할 부분 문자열을 매번 읽어오는게 아니라
기존 검증했던 부분 문자열의 처음을 제거하고 마지막의 다음위치 문자열을 추가 한 뒤 그대로 검증하는 것이다.
슬라이딩 윈도우 알고리즘 참고