Bird
Raised Fist0
Interview Prepknowing-what-to-trackmediumAmazonFacebookGoogle

Find All Anagrams in a String

Choose your preparation mode4 modes available
🎯
Find All Anagrams in a String
mediumHASH_MAPAmazonFacebookGoogle

Imagine you are analyzing a large text to find all places where a certain word's letters appear in any order, like finding all jumbled versions of 'listen' in a book.

💡 This problem is about finding all substrings that are anagrams of a given pattern. Beginners often struggle because they try to check every substring naively, which is inefficient. Understanding how to track character frequencies and use sliding windows is key.
📋
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, using all the original letters exactly once.

1 ≤ s.length, p.length ≤ 10^5s and p consist of lowercase English letters
💡
Example
Input"s = \"cbaebabacd\", p = \"abc\""
Output[0, 6]

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".

Input"s = \"abab\", p = \"ab\""
Output[0, 1, 2]

The substrings are "ab", "ba", and "ab" starting at indices 0, 1, and 2 respectively.

  • p longer than s → empty output
  • s and p are identical → output [0]
  • s or p is a single character → output all indices where characters match
  • s contains repeated characters but p has unique characters → only exact matches
⚠️
Common Mistakes
Comparing frequency maps by converting to strings or sorting every time

Leads to high time complexity and TLE

✅ Use sliding window with incremental updates and match count optimization

Not removing characters from frequency map when count drops to zero

Frequency maps differ even when substrings are anagrams, causing false negatives

✅ Remove character keys when their count reaches zero

Not handling edge cases where p is longer than s

Index errors or incorrect results

✅ Return empty list immediately if p length > s length

Off-by-one errors in sliding window boundaries

Missed or extra indices in output

✅ Carefully track window start and end indices, especially when adding/removing characters

Using mutable default arguments or global variables in recursive or iterative code

Unexpected behavior or bugs

✅ Use local variables and initialize fresh frequency maps per function call

🧠
Brute Force (Check All Substrings)
💡 This approach exists to build intuition by directly checking every possible substring of length p and verifying if it is an anagram. It is simple but inefficient, highlighting why optimization is needed.

Intuition

Check every substring of s with length equal to p, and for each substring, check if it contains the same characters with the same frequency as p.

Algorithm

  1. Iterate over all substrings of s with length equal to p.
  2. For each substring, count the frequency of characters.
  3. Compare the frequency map of the substring with that of p.
  4. If they match, record the start index.
💡 The main difficulty is realizing that checking every substring independently leads to repeated work and inefficiency.
</>
Code
from collections import Counter

def findAnagrams(s: str, p: str) -> list:
    res = []
    p_len = len(p)
    p_count = Counter(p)
    for i in range(len(s) - p_len + 1):
        window = s[i:i+p_len]
        window_count = Counter(window)
        if window_count == p_count:
            res.append(i)
    return res

# Example usage
if __name__ == '__main__':
    print(findAnagrams("cbaebabacd", "abc"))  # Output: [0, 6]
Line Notes
from collections import CounterImport Counter to easily count character frequencies
p_count = Counter(p)Precompute frequency of characters in p once
for i in range(len(s) - p_len + 1)Iterate over all possible substrings of length p_len
window_count = Counter(window)Count characters in current substring from scratch
if window_count == p_countCheck if current substring is an anagram by comparing counts
res.append(i)Record starting index if an anagram is found
import java.util.*;

public class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> res = new ArrayList<>();
        int pLen = p.length();
        Map<Character, Integer> pCount = new HashMap<>();
        for (char c : p.toCharArray()) {
            pCount.put(c, pCount.getOrDefault(c, 0) + 1);
        }
        for (int i = 0; i <= s.length() - pLen; i++) {
            String window = s.substring(i, i + pLen);
            Map<Character, Integer> windowCount = new HashMap<>();
            for (char c : window.toCharArray()) {
                windowCount.put(c, windowCount.getOrDefault(c, 0) + 1);
            }
            if (windowCount.equals(pCount)) {
                res.add(i);
            }
        }
        return res;
    }

    public static void main(String[] args) {
        Solution sol = new Solution();
        System.out.println(sol.findAnagrams("cbaebabacd", "abc")); // Output: [0, 6]
    }
}
Line Notes
Map<Character, Integer> pCount = new HashMap<>()Create frequency map for p
for (int i = 0; i <= s.length() - pLen; i++)Loop over all substrings of length pLen
Map<Character, Integer> windowCount = new HashMap<>()Create frequency map for current substring
if (windowCount.equals(pCount))Check if current substring is an anagram
res.add(i)Add starting index to result list
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>

using namespace std;

vector<int> findAnagrams(string s, string p) {
    vector<int> res;
    int pLen = p.size();
    unordered_map<char, int> pCount;
    for (char c : p) {
        pCount[c]++;
    }
    for (int i = 0; i <= (int)s.size() - pLen; i++) {
        unordered_map<char, int> windowCount;
        for (int j = i; j < i + pLen; j++) {
            windowCount[s[j]]++;
        }
        if (windowCount == pCount) {
            res.push_back(i);
        }
    }
    return res;
}

int main() {
    vector<int> result = findAnagrams("cbaebabacd", "abc");
    for (int idx : result) cout << idx << " ";
    cout << endl; // Output: 0 6
    return 0;
}
Line Notes
unordered_map<char, int> pCount;Frequency map for p
for (int i = 0; i <= (int)s.size() - pLen; i++)Iterate over all substrings of length pLen
unordered_map<char, int> windowCount;Frequency map for current substring
if (windowCount == pCount)Compare frequency maps to check anagram
res.push_back(i);Store starting index if anagram found
function findAnagrams(s, p) {
    const res = [];
    const pLen = p.length;
    const pCount = new Map();
    for (const c of p) {
        pCount.set(c, (pCount.get(c) || 0) + 1);
    }
    for (let i = 0; i <= s.length - pLen; i++) {
        const window = s.substring(i, i + pLen);
        const windowCount = new Map();
        for (const c of window) {
            windowCount.set(c, (windowCount.get(c) || 0) + 1);
        }
        if (mapsEqual(pCount, windowCount)) {
            res.push(i);
        }
    }
    return res;
}

function mapsEqual(m1, m2) {
    if (m1.size !== m2.size) return false;
    for (const [key, val] of m1) {
        if (m2.get(key) !== val) return false;
    }
    return true;
}

// Example usage
console.log(findAnagrams("cbaebabacd", "abc")); // Output: [0, 6]
Line Notes
const pCount = new Map();Create frequency map for p
for (let i = 0; i <= s.length - pLen; i++)Loop over all substrings of length pLen
const windowCount = new Map();Frequency map for current substring
if (mapsEqual(pCount, windowCount))Check if current substring is an anagram
res.push(i);Add starting index to result array
⏱
Complexity
TimeO((n - m + 1) * m) where n = len(s), m = len(p)
SpaceO(m) for frequency maps

For each of the n-m+1 substrings, we count frequencies in O(m) time, leading to O(n*m) total.

💡 If s and p are length 20, this means about 400 operations, but for 100,000 length strings this becomes 10 billion operations, which is too slow.
Interview Verdict: TLE / Use only to introduce

This approach is too slow for large inputs but is useful to understand the problem and motivate optimizations.

🧠
Sliding Window with Frequency Map Comparison
💡 This approach improves efficiency by using a sliding window to avoid recounting frequencies from scratch for every substring, reducing redundant work.

Intuition

Maintain a window of length p over s, update character counts as the window slides, and compare frequency maps incrementally.

Algorithm

  1. Create frequency map for p.
  2. Initialize a sliding window of size p_len over s.
  3. For each step, update the window frequency by adding the new character and removing the old one.
  4. Compare the window frequency map with p's frequency map; if equal, record the start index.
💡 The challenge is correctly updating counts as the window moves and efficiently comparing maps.
</>
Code
from collections import Counter

def findAnagrams(s: str, p: str) -> list:
    res = []
    p_len = len(p)
    p_count = Counter(p)
    window_count = Counter()
    for i in range(len(s)):
        window_count[s[i]] += 1
        if i >= p_len:
            left_char = s[i - p_len]
            if window_count[left_char] == 1:
                del window_count[left_char]
            else:
                window_count[left_char] -= 1
        if window_count == p_count:
            res.append(i - p_len + 1)
    return res

# Example usage
if __name__ == '__main__':
    print(findAnagrams("cbaebabacd", "abc"))  # Output: [0, 6]
Line Notes
window_count = Counter()Initialize frequency map for current window
window_count[s[i]] += 1Add new character entering the window
if i >= p_lenOnce window size exceeds p_len, remove leftmost character
if window_count[left_char] == 1Remove character from map if count drops to zero
if window_count == p_countCheck if current window is an anagram
import java.util.*;

public class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> res = new ArrayList<>();
        int pLen = p.length();
        Map<Character, Integer> pCount = new HashMap<>();
        for (char c : p.toCharArray()) {
            pCount.put(c, pCount.getOrDefault(c, 0) + 1);
        }
        Map<Character, Integer> windowCount = new HashMap<>();
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            windowCount.put(c, windowCount.getOrDefault(c, 0) + 1);
            if (i >= pLen) {
                char leftChar = s.charAt(i - pLen);
                if (windowCount.get(leftChar) == 1) {
                    windowCount.remove(leftChar);
                } else {
                    windowCount.put(leftChar, windowCount.get(leftChar) - 1);
                }
            }
            if (windowCount.equals(pCount)) {
                res.add(i - pLen + 1);
            }
        }
        return res;
    }

    public static void main(String[] args) {
        Solution sol = new Solution();
        System.out.println(sol.findAnagrams("cbaebabacd", "abc")); // Output: [0, 6]
    }
}
Line Notes
Map<Character, Integer> windowCount = new HashMap<>()Frequency map for sliding window
windowCount.put(c, windowCount.getOrDefault(c, 0) + 1)Add new character to window count
if (i >= pLen)Remove character leaving the window once window size exceeded
windowCount.remove(leftChar)Remove character if count drops to zero
if (windowCount.equals(pCount))Check if current window matches p's frequency
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>

using namespace std;

vector<int> findAnagrams(string s, string p) {
    vector<int> res;
    int pLen = p.size();
    unordered_map<char, int> pCount;
    for (char c : p) pCount[c]++;
    unordered_map<char, int> windowCount;
    for (int i = 0; i < (int)s.size(); i++) {
        windowCount[s[i]]++;
        if (i >= pLen) {
            char leftChar = s[i - pLen];
            if (windowCount[leftChar] == 1) {
                windowCount.erase(leftChar);
            } else {
                windowCount[leftChar]--;
            }
        }
        if (windowCount == pCount) {
            res.push_back(i - pLen + 1);
        }
    }
    return res;
}

int main() {
    vector<int> result = findAnagrams("cbaebabacd", "abc");
    for (int idx : result) cout << idx << " ";
    cout << endl; // Output: 0 6
    return 0;
}
Line Notes
unordered_map<char, int> windowCount;Frequency map for current sliding window
windowCount[s[i]]++;Add new character entering window
if (i >= pLen)Remove character leaving window after window size reached
windowCount.erase(leftChar);Remove character if count zero to keep map clean
if (windowCount == pCount)Compare frequency maps to detect anagram
function findAnagrams(s, p) {
    const res = [];
    const pLen = p.length;
    const pCount = new Map();
    for (const c of p) {
        pCount.set(c, (pCount.get(c) || 0) + 1);
    }
    const windowCount = new Map();
    for (let i = 0; i < s.length; i++) {
        const c = s[i];
        windowCount.set(c, (windowCount.get(c) || 0) + 1);
        if (i >= pLen) {
            const leftChar = s[i - pLen];
            if (windowCount.get(leftChar) === 1) {
                windowCount.delete(leftChar);
            } else {
                windowCount.set(leftChar, windowCount.get(leftChar) - 1);
            }
        }
        if (mapsEqual(pCount, windowCount)) {
            res.push(i - pLen + 1);
        }
    }
    return res;
}

function mapsEqual(m1, m2) {
    if (m1.size !== m2.size) return false;
    for (const [key, val] of m1) {
        if (m2.get(key) !== val) return false;
    }
    return true;
}

// Example usage
console.log(findAnagrams("cbaebabacd", "abc")); // Output: [0, 6]
Line Notes
const windowCount = new Map();Frequency map for sliding window
windowCount.set(c, (windowCount.get(c) || 0) + 1);Add new character to window count
if (i >= pLen)Remove character leaving window after window size reached
windowCount.delete(leftChar);Remove character if count zero to keep map clean
if (mapsEqual(pCount, windowCount))Check if current window matches p's frequency
⏱
Complexity
TimeO(n * k) where n = len(s), k = number of unique chars in p
SpaceO(k) for frequency maps

Each step updates counts in O(1) and compares maps in O(k), which is much faster than brute force for large n.

💡 If p has 26 unique letters, each step does about 26 comparisons, so for n=100,000 this is about 2.6 million operations, which is feasible.
Interview Verdict: Accepted / Good for medium inputs

This approach is efficient enough for most interview problems and demonstrates understanding of sliding windows and frequency tracking.

🧠
Sliding Window with Two Counters and Match Count Optimization
💡 This approach further optimizes by avoiding full map comparisons at each step, instead tracking how many characters currently match the required frequency.

Intuition

Use two frequency arrays and a match count to track how many characters have the exact needed frequency, sliding the window and updating counts and matches incrementally.

Algorithm

  1. Create frequency array for p and initialize a window frequency array.
  2. Initialize a match count to track how many characters have matching frequencies.
  3. Slide the window over s, updating counts and match count as characters enter and leave.
  4. When match count equals number of unique characters in p, record the start index.
💡 The key is carefully updating match count only when frequencies match or mismatch, avoiding costly full map comparisons.
</>
Code
def findAnagrams(s: str, p: str) -> list:
    res = []
    if len(p) > len(s):
        return res
    p_count = [0] * 26
    s_count = [0] * 26
    for c in p:
        p_count[ord(c) - ord('a')] += 1
    for i in range(len(p)):
        s_count[ord(s[i]) - ord('a')] += 1
    matches = 0
    for i in range(26):
        if p_count[i] == s_count[i]:
            matches += 1
    l = 0
    for r in range(len(p), len(s)):
        if matches == 26:
            res.append(l)
        index_r = ord(s[r]) - ord('a')
        s_count[index_r] += 1
        if s_count[index_r] == p_count[index_r]:
            matches += 1
        elif s_count[index_r] == p_count[index_r] + 1:
            matches -= 1
        index_l = ord(s[l]) - ord('a')
        s_count[index_l] -= 1
        if s_count[index_l] == p_count[index_l]:
            matches += 1
        elif s_count[index_l] == p_count[index_l] - 1:
            matches -= 1
        l += 1
    if matches == 26:
        res.append(l)
    return res

# Example usage
if __name__ == '__main__':
    print(findAnagrams("cbaebabacd", "abc"))  # Output: [0, 6]
Line Notes
p_count = [0] * 26Frequency array for p's characters
s_count = [0] * 26Frequency array for current window in s
matches = 0Count of characters whose frequency matches between p and window
if matches == 26All characters match frequency, so window is an anagram
s_count[index_r] += 1Add new character entering window
s_count[index_l] -= 1Remove character leaving window
matches += 1 / matches -= 1Update match count when frequency matches or mismatches
import java.util.*;

public class Solution {
    public List<Integer> findAnagrams(String s, String p) {
        List<Integer> res = new ArrayList<>();
        if (p.length() > s.length()) return res;
        int[] pCount = new int[26];
        int[] sCount = new int[26];
        for (char c : p.toCharArray()) pCount[c - 'a']++;
        for (int i = 0; i < p.length(); i++) sCount[s.charAt(i) - 'a']++;
        int matches = 0;
        for (int i = 0; i < 26; i++) {
            if (pCount[i] == sCount[i]) matches++;
        }
        int l = 0;
        for (int r = p.length(); r < s.length(); r++) {
            if (matches == 26) res.add(l);
            int indexR = s.charAt(r) - 'a';
            sCount[indexR]++;
            if (sCount[indexR] == pCount[indexR]) matches++;
            else if (sCount[indexR] == pCount[indexR] + 1) matches--;
            int indexL = s.charAt(l) - 'a';
            sCount[indexL]--;
            if (sCount[indexL] == pCount[indexL]) matches++;
            else if (sCount[indexL] == pCount[indexL] - 1) matches--;
            l++;
        }
        if (matches == 26) res.add(l);
        return res;
    }

    public static void main(String[] args) {
        Solution sol = new Solution();
        System.out.println(sol.findAnagrams("cbaebabacd", "abc")); // Output: [0, 6]
    }
}
Line Notes
int[] pCount = new int[26];Frequency array for p
int[] sCount = new int[26];Frequency array for sliding window
int matches = 0;Count of characters matching frequency
if (matches == 26)All characters match, window is an anagram
sCount[indexR]++;Add new character to window count
sCount[indexL]--;Remove character leaving window
matches++; matches--;Update matches when frequency changes
#include <iostream>
#include <vector>
#include <string>

using namespace std;

vector<int> findAnagrams(string s, string p) {
    vector<int> res;
    if (p.size() > s.size()) return res;
    vector<int> pCount(26, 0), sCount(26, 0);
    for (char c : p) pCount[c - 'a']++;
    for (int i = 0; i < (int)p.size(); i++) sCount[s[i] - 'a']++;
    int matches = 0;
    for (int i = 0; i < 26; i++) {
        if (pCount[i] == sCount[i]) matches++;
    }
    int l = 0;
    for (int r = (int)p.size(); r < (int)s.size(); r++) {
        if (matches == 26) res.push_back(l);
        int indexR = s[r] - 'a';
        sCount[indexR]++;
        if (sCount[indexR] == pCount[indexR]) matches++;
        else if (sCount[indexR] == pCount[indexR] + 1) matches--;
        int indexL = s[l] - 'a';
        sCount[indexL]--;
        if (sCount[indexL] == pCount[indexL]) matches++;
        else if (sCount[indexL] == pCount[indexL] - 1) matches--;
        l++;
    }
    if (matches == 26) res.push_back(l);
    return res;
}

int main() {
    vector<int> result = findAnagrams("cbaebabacd", "abc");
    for (int idx : result) cout << idx << " ";
    cout << endl; // Output: 0 6
    return 0;
}
Line Notes
vector<int> pCount(26, 0), sCount(26, 0);Frequency arrays for p and window
int matches = 0;Count of characters matching frequency
if (matches == 26)All characters match, window is an anagram
sCount[indexR]++;Add new character to window count
sCount[indexL]--;Remove character leaving window
matches++; matches--;Update matches when frequency changes
function findAnagrams(s, p) {
    const res = [];
    if (p.length > s.length) return res;
    const pCount = new Array(26).fill(0);
    const sCount = new Array(26).fill(0);
    for (const c of p) pCount[c.charCodeAt(0) - 97]++;
    for (let i = 0; i < p.length; i++) sCount[s.charCodeAt(i) - 97]++;
    let matches = 0;
    for (let i = 0; i < 26; i++) {
        if (pCount[i] === sCount[i]) matches++;
    }
    let l = 0;
    for (let r = p.length; r < s.length; r++) {
        if (matches === 26) res.push(l);
        let indexR = s.charCodeAt(r) - 97;
        sCount[indexR]++;
        if (sCount[indexR] === pCount[indexR]) matches++;
        else if (sCount[indexR] === pCount[indexR] + 1) matches--;
        let indexL = s.charCodeAt(l) - 97;
        sCount[indexL]--;
        if (sCount[indexL] === pCount[indexL]) matches++;
        else if (sCount[indexL] === pCount[indexL] - 1) matches--;
        l++;
    }
    if (matches === 26) res.push(l);
    return res;
}

// Example usage
console.log(findAnagrams("cbaebabacd", "abc")); // Output: [0, 6]
Line Notes
const pCount = new Array(26).fill(0);Frequency array for p
const sCount = new Array(26).fill(0);Frequency array for sliding window
let matches = 0;Count of characters matching frequency
if (matches === 26)All characters match, window is an anagram
sCount[indexR]++;Add new character to window count
sCount[indexL]--;Remove character leaving window
matches++; matches--;Update matches when frequency changes
⏱
Complexity
TimeO(n) where n = len(s)
SpaceO(1) since frequency arrays are fixed size 26

Each character is processed once, and match count updates are O(1), making this the most efficient approach.

💡 For n=100,000, this approach does about 100,000 operations, which is very fast and scalable.
Interview Verdict: Accepted / Optimal

This is the best approach to implement in interviews for this problem, showing mastery of sliding window and frequency tracking.

📊
All Approaches - One-Glance Tradeoffs
💡 In interviews, coding the optimal sliding window with match count approach is best. Brute force is only for explanation, and the basic sliding window is a good intermediate step.
ApproachTimeSpaceStack RiskReconstructUse In Interview
1. Brute ForceO(n*m)O(m)NoN/AMention only - never code
2. Sliding Window with Frequency Map ComparisonO(n*k) where k = unique chars in pO(k)NoN/AGood intermediate solution
3. Sliding Window with Match Count OptimizationO(n)O(1)NoN/ACode this for best performance
💼
Interview Strategy
💡 Use this guide to understand the problem deeply before interviews. Start by clarifying the problem, then explain the brute force approach to show understanding. Progress to optimized sliding window solutions, and finally discuss edge cases and test thoroughly.

How to Present

Step 1: Clarify the problem and constraints with the interviewer.Step 2: Describe the brute force approach and its inefficiency.Step 3: Introduce the sliding window technique with frequency maps.Step 4: Optimize further by tracking matches to avoid full map comparisons.Step 5: Code the optimal solution and test with examples and edge cases.

Time Allocation

Clarify: 2min → Approach: 5min → Code: 10min → Test: 3min. Total ~20min

What the Interviewer Tests

The interviewer tests your ability to identify the right data structures (frequency maps), use sliding windows effectively, optimize comparisons, and handle edge cases correctly.

Common Follow-ups

  • What if the input contains Unicode characters? → Use hash maps instead of fixed arrays.
  • Can you find the first anagram instead of all? → Stop when first match found.
💡 These follow-ups test your adaptability to variations and understanding of data structures beyond ASCII.
🔍
Pattern Recognition

When to Use

1) Asked to find substrings matching a pattern's character composition, 2) Need to find all occurrences, 3) Order of characters doesn't matter, 4) Efficient substring checking required.

Signature Phrases

'find all start indices of p's anagrams in s''rearranging the letters'

NOT This Pattern When

Substring search problems where order matters or exact substring matching is required (e.g., KMP algorithm problems).

Similar Problems

Minimum Window Substring - similar frequency tracking but with minimum length windowPermutation in String - check if any permutation of p is substring of sGroup Anagrams - group strings by character frequency signature

Practice

(1/5)
1. The following code attempts to solve the fruits problem using a sliding window. Identify the line containing the subtle bug that causes incorrect results on some inputs.
def totalFruit(fruits):
    basket = {}
    left = 0
    max_length = 0
    for right in range(len(fruits)):
        basket[fruits[right]] = basket.get(fruits[right], 0) + 1
        while len(basket) > 2:
            basket[fruits[left]] -= 1
            # BUG: Missing removal of fruit type when count reaches zero
            left += 1
        max_length = max(max_length, right - left + 1)
    return max_length
medium
A. Line where basket[fruits[right]] is incremented
B. Line where basket[fruits[left]] is decremented
C. Line where fruit type is deleted when count reaches zero (missing here)
D. Line where max_length is updated

Solution

  1. Step 1: Identify missing removal of fruit type

    When basket[fruits[left]] count reaches zero, the fruit type must be deleted to keep basket size accurate.
  2. Step 2: Consequence of missing deletion

    Without deletion, basket size remains > 2 incorrectly, causing unnecessary window shrinking and wrong max length.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Deleting fruit type when count hits zero is essential [OK]
Hint: Check if fruit count zero triggers deletion [OK]
Common Mistakes:
  • Forgetting to delete fruit type
  • Shrinking window too early
  • Updating max_length incorrectly
2. What is the time complexity of the optimal sliding window algorithm using an ordered dictionary to find the longest substring with at most k distinct characters, where n is the length of the string and k is the maximum distinct characters allowed?
medium
A. O(n * k)
B. O(n)
C. O(n log k)
D. O(n^2)

Solution

  1. Step 1: Identify outer loop complexity

    The algorithm iterates over each character once, so the outer loop is O(n).
  2. Step 2: Analyze operations inside loop

    OrderedDict operations (deletion and insertion) are O(1) amortized, and each character is added and removed at most once, so total is O(n).
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Each character processed once with O(1) ops -> O(n) [OK]
Hint: OrderedDict operations are O(1) amortized, total O(n) [OK]
Common Mistakes:
  • Assuming O(n * k) due to nested loops
  • Thinking ordered dictionary operations cost O(log k)
3. Identify the bug in the following code snippet for the Maximum Points You Can Obtain from Cards problem:
medium
A. Line 7: Loop range should start from k instead of window_size.
B. Line 4: Incorrect initial sum calculation; should sum last k elements instead of first window_size.
C. Line 9: The condition should be current_sum > min_subarray_sum instead of <.
D. Line 3: Incorrect calculation of window_size; should be n - k instead of k.

Solution

  1. Step 1: Understand window size meaning

    The window represents the subarray to exclude, which must be length n - k, not k.
  2. Step 2: Identify impact of wrong window size

    Using k as window size causes the algorithm to exclude wrong subarray length, leading to incorrect results.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Correct window size is n - k for the sliding window [OK]
Hint: Window size must be n - k, not k [OK]
Common Mistakes:
  • Confusing window size with k instead of n-k
  • Incorrect loop boundaries
  • Wrong comparison operator in min update
4. Suppose the problem is modified so that the array can contain negative integers and zeros, and you want to count subarrays with exactly k odd numbers. Which modification to the sliding window approach is necessary to handle this variant correctly?
hard
A. Modify the odd number check to use absolute value: nums[right] % 2 != 0
B. No modification needed; the existing sliding window works for any integers
C. Use prefix sums of odd counts instead of sliding window to handle negatives
D. Sliding window must reset when encountering negative numbers to avoid incorrect counts

Solution

  1. Step 1: Identify odd number condition with negatives

    Negative odd numbers still have odd absolute value, so check must consider absolute value.
  2. Step 2: Modify odd check

    Change condition to nums[right] % 2 != 0 or abs(nums[right]) % 2 == 1 to correctly count odd numbers.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Oddness depends on absolute value, not sign [OK]
Hint: Oddness depends on absolute value, not sign [OK]
Common Mistakes:
  • Assuming negative numbers are never odd
  • Resetting sliding window unnecessarily
  • Switching to prefix sums without need
5. Suppose the problem is modified so that characters in t can be reused unlimited times (i.e., the substring in s must contain at least one occurrence of each character in t, but counts do not matter). Which modification to the sliding window algorithm correctly solves this variant?
hard
A. Keep frequency counts and require window_count[c] >= t_count[c] for all c, same as original
B. Use brute force to check all substrings since counts no longer matter
C. Sort s and t and use two pointers to find minimal substring
D. Track only presence of characters from t in the window, increment have when a character appears at least once, decrement when it disappears

Solution

  1. Step 1: Understand problem change

    Since counts do not matter, only presence of each character is required, so frequency counts can be replaced by boolean presence tracking.
  2. Step 2: Modify sliding window logic

    Increment have when a character from t appears first time in window, decrement when it leaves. Shrink window when all characters are present.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Tracking presence instead of counts solves the reuse variant efficiently [OK]
Hint: Track presence, not counts, when duplicates don't matter [OK]
Common Mistakes:
  • Using original count-based logic
  • Assuming brute force is needed
  • Sorting breaks substring order
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard