Find All Anagrams in a String medium
Problem Statement
Given two strings s
and p
, return an array of all the start indices of p
's anagrams in s
. You may return the answer in any order.
An anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.
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".
Steps and Explanation
The core idea is to use a sliding window approach and character frequency counting. We maintain a frequency map (using a HashMap
in Java) for the characters in the pattern p
. Then, we slide a window of the same size as p
across the string s
. For each window, we compare its character frequencies with those of p
. If they match, we've found an anagram.
-
Create Frequency Map for
p
: Count the occurrences of each character inp
and store them in aHashMap
. -
Sliding Window: Initialize a sliding window of size
p.length()
at the beginning ofs
. -
Frequency Map for Window: Create a frequency map for the current window in
s
. -
Comparison: Compare the frequency maps of the window and
p
. If they are identical, add the start index of the window to the result list. -
Slide the Window: Move the window one position to the right. Update the frequency map by subtracting the frequency of the character leaving the window and adding the frequency of the character entering the window.
-
Repeat: Continue steps 3-5 until the window reaches the end of
s
.
Code (Java)
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class Solution {
public List<Integer> findAnagrams(String s, String p) {
List<Integer> result = new ArrayList<>();
if (s == null || p == null || s.length() < p.length()) {
return result; // Handle edge cases
}
Map<Character, Integer> pFreq = new HashMap<>();
for (char c : p.toCharArray()) {
pFreq.put(c, pFreq.getOrDefault(c, 0) + 1);
}
Map<Character, Integer> windowFreq = new HashMap<>();
int windowStart = 0;
int windowEnd = 0;
while (windowEnd < s.length()) {
char c = s.charAt(windowEnd);
windowFreq.put(c, windowFreq.getOrDefault(c, 0) + 1);
if (windowEnd - windowStart + 1 == p.length()) {
if (windowFreq.equals(pFreq)) {
result.add(windowStart);
}
char leftChar = s.charAt(windowStart);
windowFreq.put(leftChar, windowFreq.get(leftChar) - 1);
if (windowFreq.get(leftChar) == 0) {
windowFreq.remove(leftChar);
}
windowStart++;
}
windowEnd++;
}
return result;
}
}
Complexity Analysis
-
Time Complexity: O(n), where n is the length of string
s
. We iterate throughs
once using the sliding window. HashMap operations (get, put) are on average O(1). -
Space Complexity: O(1). The HashMaps store character frequencies; the size of the HashMaps is bounded by the size of the alphabet (26 for lowercase English letters), which is a constant. The
result
list can at most containn
elements in the worst case. However, space complexity is still considered O(1) because it is not dependent on the input size.