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.
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".
Constraints:
1 <= s.length, p.length <= 3 * 104
s
and p
consist of lowercase English letters.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The goal is to find all occurrences of anagrams of a given pattern within a larger text. A brute force approach involves checking every possible substring within the text to see if it is an anagram of the pattern. This means we'll go through the text, look at chunks of the right size, and compare them to the pattern.
Here's how the algorithm would work step-by-step:
def find_all_anagrams_brute_force(text, pattern):
anagram_indices = []
pattern_length = len(pattern)
text_length = len(text)
for index in range(text_length - pattern_length + 1):
substring = text[index:index + pattern_length]
# We use character counts to check for anagrams
if is_anagram(substring, pattern):
anagram_indices.append(index)
return anagram_indices
def is_anagram(substring, pattern):
if len(substring) != len(pattern):
return False
pattern_character_counts = {}
for char in pattern:
pattern_character_counts[char] = pattern_character_counts.get(char, 0) + 1
substring_character_counts = {}
for char in substring:
substring_character_counts[char] = substring_character_counts.get(char, 0) + 1
# Compare the counts of each character.
if pattern_character_counts == substring_character_counts:
return True
else:
return False
We want to find all the places in a big string where a smaller string's letters appear, but in any order. The key idea is to use a sliding window that only moves forward, avoiding redundant checks by cleverly updating the letter counts as it goes.
Here's how the algorithm would work step-by-step:
def find_all_anagrams_in_string(main_string, pattern_string):
anagram_indices = []
pattern_length = len(pattern_string)
main_string_length = len(main_string)
if pattern_length > main_string_length:
return anagram_indices
pattern_character_counts = {}
for character in pattern_string:
pattern_character_counts[character] = pattern_character_counts.get(character, 0) + 1
window_character_counts = {}
# Initialize the sliding window's character counts.
for i in range(pattern_length):
current_character = main_string[i]
window_character_counts[current_character] = window_character_counts.get(current_character, 0) + 1
# This checks if the initial window is an anagram.
if window_character_counts == pattern_character_counts:
anagram_indices.append(0)
for i in range(1, main_string_length - pattern_length + 1):
# Remove the leftmost character from the window.
left_character = main_string[i - 1]
window_character_counts[left_character] -= 1
if window_character_counts[left_character] == 0:
del window_character_counts[left_character]
# Add the rightmost character to the window.
right_character = main_string[i + pattern_length - 1]
window_character_counts[right_character] = window_character_counts.get(right_character, 0) + 1
# Check if the current window is an anagram.
if window_character_counts == pattern_character_counts:
# Add the starting index of the anagram to result.
anagram_indices.append(i)
return anagram_indices
Case | How to Handle |
---|---|
s or p is null or empty | Return an empty list if either string is null or empty, as no anagram can exist. |
p is longer than s | Return an empty list because p cannot be an anagram of any substring of s. |
s and p are the same string (trivial anagram) | Return index 0 as the only anagram start index. |
s and p have the same length but are not anagrams | Return an empty list since no anagram exists. |
s contains only one unique character repeated many times, p contains only one unique character repeated fewer times | Sliding window will check all possible windows and return starting indices where counts match. |
p contains duplicate characters | Character frequency maps or arrays correctly handle duplicate characters in p when comparing with substrings of s. |
s is very long, potentially causing performance issues if the sliding window or frequency map comparison is inefficient. | Ensure the solution uses an efficient O(n) algorithm like sliding window with constant time frequency map comparison. |
s and p contains unicode characters | Use a hash map that can accommodate all unicode characters to store counts, or adjust array size if known character set is limited |