Facebook Pixel

2953. Count Complete Substrings

HardHash TableStringSliding Window
Leetcode Link

Problem Description

You are given a string word and an integer k.

A substring is considered complete if it satisfies two conditions:

  1. Equal frequency condition: Every character that appears in the substring must occur exactly k times.

  2. Adjacent character condition: For any two adjacent characters in the substring, their positions in the alphabet must differ by at most 2. In other words, if you have two adjacent characters c1 and c2, then |ord(c1) - ord(c2)| ≤ 2.

Your task is to count how many complete substrings exist in the given string word.

For example, if we have adjacent characters 'a' and 'c', their difference is |97 - 99| = 2, which satisfies the condition. However, 'a' and 'd' would have a difference of |97 - 100| = 3, which violates the condition.

The solution approach involves:

  • First splitting the string into segments where all adjacent characters satisfy the alphabet distance condition (differ by at most 2)
  • For each segment, using a sliding window technique to find all substrings where each character appears exactly k times
  • The window size is determined by the number of unique characters (i) multiplied by k, since each of the i characters must appear exactly k times
  • Using frequency counters to efficiently track when a window contains exactly i characters, each appearing exactly k times
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key insight is recognizing that the two conditions create natural boundaries in our string. The second condition (adjacent characters must differ by at most 2) acts as a "breaking point" - whenever we encounter two adjacent characters that differ by more than 2, we know that no complete substring can span across this boundary.

This observation leads us to split the original string into segments where all adjacent characters satisfy the alphabet distance constraint. For example, if we have "abcfgh", we'd split it at 'c' and 'f' since |ord('c') - ord('f')| = 3 > 2.

Once we have these segments, we need to find all substrings within each segment where every character appears exactly k times. But how do we efficiently check this?

Here's where the mathematical insight comes in: if a substring has i unique characters and each must appear exactly k times, then the substring must have exactly i × k characters. This gives us fixed-size windows to check!

For instance, if k = 2:

  • A substring with 1 unique character must have length 2 (like "aa")
  • A substring with 2 unique characters must have length 4 (like "aabb")
  • A substring with 3 unique characters must have length 6 (like "aabbcc")

Since we're dealing with lowercase English letters, we have at most 26 unique characters, so we only need to check window sizes from k to 26k.

The sliding window technique becomes natural here - for each possible window size l = i × k, we slide a window of that size across the segment. We maintain:

  • cnt: frequency of each character in the current window
  • freq: frequency of frequencies (how many characters appear exactly j times)

When freq[k] == i, it means we have exactly i characters, each appearing exactly k times - a complete substring!

This approach elegantly combines the problem's constraints with fixed-size sliding windows, making it efficient to count all complete substrings.

Learn more about Sliding Window patterns.

Solution Approach

The implementation consists of two main parts: splitting the string into valid segments and counting complete substrings within each segment.

Step 1: Splitting the String into Valid Segments

We use two pointers i and j to identify segments where all adjacent characters differ by at most 2:

while i < n:
    j = i + 1
    while j < n and abs(ord(word[j]) - ord(word[j - 1])) <= 2:
        j += 1
    ans += f(word[i:j])
    i = j

Starting from position i, we extend j as long as the adjacent character condition is satisfied. Once we find a breaking point, we process the segment word[i:j] and move to the next segment.

Step 2: Counting Complete Substrings in Each Segment

The helper function f(s) counts complete substrings within a segment s. For each possible number of unique characters i (from 1 to 26):

  1. Calculate window size: l = i * k (since we need i characters, each appearing k times)

  2. Initialize the first window: Create a frequency counter cnt for the first l characters, and a frequency-of-frequencies counter freq that tracks how many characters appear exactly j times.

  3. Check initial window: If freq[k] == i, we have found a complete substring (all i characters appear exactly k times).

  4. Slide the window: For each new position j from l to m-1:

    • Add new character s[j]:

      freq[cnt[s[j]]] -= 1  # Remove old frequency count
      cnt[s[j]] += 1         # Increment character count
      freq[cnt[s[j]]] += 1   # Add new frequency count
    • Remove old character s[j-l]:

      freq[cnt[s[j-l]]] -= 1  # Remove old frequency count
      cnt[s[j-l]] -= 1        # Decrement character count
      freq[cnt[s[j-l]]] += 1  # Add new frequency count
    • Check condition: If freq[k] == i, increment the answer.

Key Data Structures:

  • cnt: A Counter that maintains character frequencies in the current window
  • freq: A Counter that maintains how many characters have each frequency value

Why This Works:

The freq counter is the key optimization. Instead of checking if all characters in the window appear exactly k times (which would require iterating through cnt), we maintain a count of frequencies. When freq[k] == i, it means exactly i characters have frequency k, and since our window has size i * k, these must be the only characters in the window.

Time Complexity:

  • For each segment, we iterate through at most 26 different window sizes
  • For each window size, we slide through the segment once
  • Overall: O(26 * n) = O(n) where n is the length of the string

Ready to land your dream job?

Unlock your dream job with a 3-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through a concrete example with word = "ababcd" and k = 2.

Step 1: Split into valid segments

We check adjacent characters:

  • 'a' and 'b': |97 - 98| = 1 ≤ 2
  • 'b' and 'a': |98 - 97| = 1 ≤ 2
  • 'a' and 'b': |97 - 98| = 1 ≤ 2
  • 'b' and 'c': |98 - 99| = 1 ≤ 2
  • 'c' and 'd': |99 - 100| = 1 ≤ 2

All adjacent characters satisfy the condition, so we have one segment: "ababcd".

Step 2: Count complete substrings in segment "ababcd"

We check different window sizes based on the number of unique characters:

For i = 1 (window size = 1 × 2 = 2):

  • Window "ab": cnt = {'a':1, 'b':1}, freq = {1:2}, freq[2] = 0 ≠ 1 ✗
  • Window "ba": cnt = {'b':1, 'a':1}, freq = {1:2}, freq[2] = 0 ≠ 1 ✗
  • Window "ab": cnt = {'a':1, 'b':1}, freq = {1:2}, freq[2] = 0 ≠ 1 ✗
  • Window "bc": cnt = {'b':1, 'c':1}, freq = {1:2}, freq[2] = 0 ≠ 1 ✗
  • Window "cd": cnt = {'c':1, 'd':1}, freq = {1:2}, freq[2] = 0 ≠ 1 ✗

No complete substrings of size 2.

For i = 2 (window size = 2 × 2 = 4):

  • Window "abab": cnt = {'a':2, 'b':2}, freq = {2:2}, freq[2] = 2 ✓ (Found one!)
  • Window "babc": cnt = {'b':2, 'a':1, 'c':1}, freq = {1:2, 2:1}, freq[2] = 1 ≠ 2 ✗
  • Window "abcd": cnt = {'a':1, 'b':1, 'c':1, 'd':1}, freq = {1:4}, freq[2] = 0 ≠ 2 ✗

Found 1 complete substring: "abab".

For i = 3 (window size = 3 × 2 = 6):

  • Window "ababcd": cnt = {'a':2, 'b':2, 'c':1, 'd':1}, freq = {1:2, 2:2}, freq[2] = 2 ≠ 3 ✗

No complete substrings of size 6.

Total count: 1

The only complete substring is "abab" where:

  • Each character ('a' and 'b') appears exactly k=2 times
  • All adjacent characters differ by at most 2 (|'a'-'b'| = 1)

Let's trace through word = "aabaab" with k = 3.

Phase 1: Segment identification Check each adjacent pair:

  • 'a','a': |97-97| = 0 ≤ 2 ✓
  • 'a','b': |97-98| = 1 ≤ 2 ✓
  • 'b','a': |98-97| = 1 ≤ 2 ✓
  • 'a','a': |97-97| = 0 ≤ 2 ✓
  • 'a','b': |97-98| = 1 ≤ 2 ✓

Result: One segment "aabaab" (length 6)

Phase 2: Window sliding for each possible unique character count

Window size for i=1: 1×3=3

  • Position 0-2: "aab" → cnt={'a':2,'b':1}, freq={1:1,2:1}, need freq[3]=1 but have 0 ✗
  • Position 1-3: "aba" → cnt={'a':2,'b':1}, freq={1:1,2:1}, freq[3]=0 ✗
  • Position 2-4: "baa" → cnt={'b':1,'a':2}, freq={1:1,2:1}, freq[3]=0 ✗
  • Position 3-5: "aab" → cnt={'a':2,'b':1}, freq={1:1,2:1}, freq[3]=0 ✗

Window size for i=2: 2×3=6

  • Position 0-5: "aabaab" → cnt={'a':4,'b':2}, freq={2:1,4:1}, need freq[3]=2 but have 0 ✗

Result: 0 complete substrings

None of the substrings satisfy both conditions - no character appears exactly 3 times in any valid window.

Solution Implementation

1from collections import Counter
2
3class Solution:
4    def countCompleteSubstrings(self, word: str, k: int) -> int:
5        def count_complete_in_segment(segment: str) -> int:
6            """
7            Count complete substrings in a segment where adjacent chars differ by at most 2.
8            A complete substring has each character appearing exactly k times.
9            """
10            segment_length = len(segment)
11            result = 0
12          
13            # Try all possible numbers of unique characters (1 to 26)
14            for num_unique_chars in range(1, 27):
15                # Calculate the required window size
16                window_size = num_unique_chars * k
17              
18                # Skip if window size exceeds segment length
19                if window_size > segment_length:
20                    break
21              
22                # Initialize counters for the first window
23                char_count = Counter(segment[:window_size])
24                frequency_count = Counter(char_count.values())
25              
26                # Check if first window is complete (all chars appear exactly k times)
27                result += frequency_count[k] == num_unique_chars
28              
29                # Slide the window through the rest of the segment
30                for right in range(window_size, segment_length):
31                    # Character entering the window
32                    entering_char = segment[right]
33                  
34                    # Update frequency counter before changing char count
35                    frequency_count[char_count[entering_char]] -= 1
36                    char_count[entering_char] += 1
37                    frequency_count[char_count[entering_char]] += 1
38                  
39                    # Character leaving the window
40                    leaving_char = segment[right - window_size]
41                  
42                    # Update frequency counter before changing char count
43                    frequency_count[char_count[leaving_char]] -= 1
44                    char_count[leaving_char] -= 1
45                    frequency_count[char_count[leaving_char]] += 1
46                  
47                    # Check if current window is complete
48                    result += frequency_count[k] == num_unique_chars
49                  
50            return result
51      
52        # Main function logic
53        total_count = 0
54        string_length = len(word)
55        start_index = 0
56      
57        # Split the string into segments where adjacent chars differ by at most 2
58        while start_index < string_length:
59            end_index = start_index + 1
60          
61            # Extend segment while adjacent characters differ by at most 2
62            while end_index < string_length and abs(ord(word[end_index]) - ord(word[end_index - 1])) <= 2:
63                end_index += 1
64          
65            # Count complete substrings in this segment
66            total_count += count_complete_in_segment(word[start_index:end_index])
67          
68            # Move to next segment
69            start_index = end_index
70          
71        return total_count
72
1class Solution {
2    /**
3     * Counts the number of complete substrings in the given word.
4     * A complete substring has all characters appearing exactly k times,
5     * and adjacent characters differ by at most 2 in ASCII value.
6     * 
7     * @param word the input string
8     * @param k the required frequency for each character
9     * @return the count of complete substrings
10     */
11    public int countCompleteSubstrings(String word, int k) {
12        int n = word.length();
13        int totalCount = 0;
14      
15        // Process segments where adjacent characters differ by at most 2
16        for (int startIdx = 0; startIdx < n;) {
17            int endIdx = startIdx + 1;
18          
19            // Find the end of current segment where adjacent chars differ by at most 2
20            while (endIdx < n && Math.abs(word.charAt(endIdx) - word.charAt(endIdx - 1)) <= 2) {
21                endIdx++;
22            }
23          
24            // Count complete substrings in this segment
25            totalCount += countCompleteInSegment(word.substring(startIdx, endIdx), k);
26            startIdx = endIdx;
27        }
28      
29        return totalCount;
30    }
31
32    /**
33     * Counts complete substrings within a segment where each character appears exactly k times.
34     * Uses sliding window technique for each possible number of distinct characters.
35     * 
36     * @param segment the string segment to process
37     * @param k the required frequency for each character
38     * @return the count of complete substrings in the segment
39     */
40    private int countCompleteInSegment(String segment, int k) {
41        int segmentLength = segment.length();
42        int completeSubstrCount = 0;
43      
44        // Try windows with i distinct characters (1 to 26)
45        for (int distinctChars = 1; distinctChars <= 26 && distinctChars * k <= segmentLength; distinctChars++) {
46            int windowSize = distinctChars * k;
47            int[] charFrequency = new int[26];
48          
49            // Initialize the first window
50            for (int j = 0; j < windowSize; j++) {
51                charFrequency[segment.charAt(j) - 'a']++;
52            }
53          
54            // Track frequency distribution using a map
55            // Key: frequency value, Value: count of characters with that frequency
56            Map<Integer, Integer> frequencyDistribution = new HashMap<>();
57            for (int freq : charFrequency) {
58                if (freq > 0) {
59                    frequencyDistribution.merge(freq, 1, Integer::sum);
60                }
61            }
62          
63            // Check if all distinctChars characters have frequency k
64            if (frequencyDistribution.getOrDefault(k, 0) == distinctChars) {
65                completeSubstrCount++;
66            }
67          
68            // Slide the window through the rest of the segment
69            for (int rightIdx = windowSize; rightIdx < segmentLength; rightIdx++) {
70                int leftIdx = rightIdx - windowSize;
71                int newCharIndex = segment.charAt(rightIdx) - 'a';
72                int oldCharIndex = segment.charAt(leftIdx) - 'a';
73              
74                // Update frequency distribution for the new character
75                frequencyDistribution.merge(charFrequency[newCharIndex], -1, Integer::sum);
76                charFrequency[newCharIndex]++;
77                frequencyDistribution.merge(charFrequency[newCharIndex], 1, Integer::sum);
78              
79                // Update frequency distribution for the removed character
80                frequencyDistribution.merge(charFrequency[oldCharIndex], -1, Integer::sum);
81                charFrequency[oldCharIndex]--;
82                frequencyDistribution.merge(charFrequency[oldCharIndex], 1, Integer::sum);
83              
84                // Check if current window forms a complete substring
85                if (frequencyDistribution.getOrDefault(k, 0) == distinctChars) {
86                    completeSubstrCount++;
87                }
88            }
89        }
90      
91        return completeSubstrCount;
92    }
93}
94
1class Solution {
2public:
3    int countCompleteSubstrings(string word, int k) {
4        int n = word.length();
5        int totalCount = 0;
6      
7        // Helper function to count complete substrings in a valid segment
8        // A complete substring has each character appearing exactly k times
9        auto countCompleteInSegment = [&](string segment) {
10            int segmentLength = segment.length();
11            int count = 0;
12          
13            // Try all possible number of unique characters (1 to 26)
14            for (int uniqueChars = 1; uniqueChars <= 26 && uniqueChars * k <= segmentLength; ++uniqueChars) {
15                int windowSize = uniqueChars * k;  // Each of uniqueChars chars appears k times
16                int charFrequency[26]{};  // Frequency of each character in current window
17              
18                // Initialize the first window
19                for (int j = 0; j < windowSize; ++j) {
20                    ++charFrequency[segment[j] - 'a'];
21                }
22              
23                // Count how many characters have each frequency value
24                unordered_map<int, int> frequencyCount;
25                for (int freq : charFrequency) {
26                    if (freq > 0) {
27                        frequencyCount[freq]++;
28                    }
29                }
30              
31                // Check if all uniqueChars characters appear exactly k times
32                if (frequencyCount[k] == uniqueChars) {
33                    ++count;
34                }
35              
36                // Slide the window through the segment
37                for (int j = windowSize; j < segmentLength; ++j) {
38                    int addedChar = segment[j] - 'a';        // Character entering the window
39                    int removedChar = segment[j - windowSize] - 'a';  // Character leaving the window
40                  
41                    // Update frequency count for the added character
42                    frequencyCount[charFrequency[addedChar]]--;
43                    charFrequency[addedChar]++;
44                    frequencyCount[charFrequency[addedChar]]++;
45                  
46                    // Update frequency count for the removed character
47                    frequencyCount[charFrequency[removedChar]]--;
48                    charFrequency[removedChar]--;
49                    frequencyCount[charFrequency[removedChar]]++;
50                  
51                    // Check if current window forms a complete substring
52                    if (frequencyCount[k] == uniqueChars) {
53                        ++count;
54                    }
55                }
56            }
57            return count;
58        };
59      
60        // Split the word into segments where consecutive characters differ by at most 2
61        for (int i = 0; i < n;) {
62            int j = i + 1;
63          
64            // Extend segment while consecutive characters satisfy the constraint
65            while (j < n && abs(word[j] - word[j - 1]) <= 2) {
66                ++j;
67            }
68          
69            // Count complete substrings in this valid segment
70            totalCount += countCompleteInSegment(word.substr(i, j - i));
71          
72            // Move to the next segment
73            i = j;
74        }
75      
76        return totalCount;
77    }
78};
79
1/**
2 * Counts the number of complete substrings in a word where:
3 * - Each character appears exactly k times
4 * - Adjacent characters have ASCII difference at most 2
5 * @param word - The input string to analyze
6 * @param k - The required frequency for each character
7 * @returns The count of complete substrings
8 */
9function countCompleteSubstrings(word: string, k: number): number {
10    /**
11     * Helper function to count complete substrings in a segment
12     * where all adjacent characters have ASCII difference at most 2
13     * @param segment - A substring where adjacent chars differ by at most 2
14     * @returns Count of complete substrings in this segment
15     */
16    const countCompleteInSegment = (segment: string): number => {
17        const segmentLength = segment.length;
18        let completeCount = 0;
19      
20        // Try all possible numbers of unique characters (1 to 26)
21        for (let uniqueChars = 1; uniqueChars <= 26 && uniqueChars * k <= segmentLength; uniqueChars++) {
22            // Window size for current number of unique characters
23            const windowSize = uniqueChars * k;
24          
25            // Character frequency array for current window (26 letters)
26            const charFrequency: number[] = new Array(26).fill(0);
27          
28            // Initialize first window
29            for (let i = 0; i < windowSize; i++) {
30                const charIndex = segment.charCodeAt(i) - 'a'.charCodeAt(0);
31                charFrequency[charIndex]++;
32            }
33          
34            // Frequency map: maps frequency value to count of characters with that frequency
35            const frequencyMap: { [key: number]: number } = {};
36            for (const freq of charFrequency) {
37                if (freq > 0) {
38                    frequencyMap[freq] = (frequencyMap[freq] || 0) + 1;
39                }
40            }
41          
42            // Check if first window is complete (all chars appear exactly k times)
43            if (frequencyMap[k] === uniqueChars) {
44                completeCount++;
45            }
46          
47            // Slide the window through the segment
48            for (let rightIndex = windowSize; rightIndex < segmentLength; rightIndex++) {
49                // Character entering the window
50                const enteringCharIndex = segment.charCodeAt(rightIndex) - 'a'.charCodeAt(0);
51                // Character leaving the window
52                const leavingCharIndex = segment.charCodeAt(rightIndex - windowSize) - 'a'.charCodeAt(0);
53              
54                // Update frequency map for entering character
55                frequencyMap[charFrequency[enteringCharIndex]]--;
56                charFrequency[enteringCharIndex]++;
57                frequencyMap[charFrequency[enteringCharIndex]] = (frequencyMap[charFrequency[enteringCharIndex]] || 0) + 1;
58              
59                // Update frequency map for leaving character
60                frequencyMap[charFrequency[leavingCharIndex]]--;
61                charFrequency[leavingCharIndex]--;
62                frequencyMap[charFrequency[leavingCharIndex]] = (frequencyMap[charFrequency[leavingCharIndex]] || 0) + 1;
63              
64                // Check if current window is complete
65                if (frequencyMap[k] === uniqueChars) {
66                    completeCount++;
67                }
68            }
69        }
70      
71        return completeCount;
72    };
73  
74    const wordLength = word.length;
75    let totalCompleteSubstrings = 0;
76  
77    // Split word into segments where adjacent characters differ by at most 2
78    let segmentStart = 0;
79    while (segmentStart < wordLength) {
80        let segmentEnd = segmentStart + 1;
81      
82        // Extend segment while adjacent characters differ by at most 2
83        while (segmentEnd < wordLength && 
84               Math.abs(word.charCodeAt(segmentEnd) - word.charCodeAt(segmentEnd - 1)) <= 2) {
85            segmentEnd++;
86        }
87      
88        // Process current segment and add complete substrings count
89        const currentSegment = word.substring(segmentStart, segmentEnd);
90        totalCompleteSubstrings += countCompleteInSegment(currentSegment);
91      
92        // Move to next segment
93        segmentStart = segmentEnd;
94    }
95  
96    return totalCompleteSubstrings;
97}
98

Time and Space Complexity

Time Complexity: O(n × |Σ|) where n is the length of the string word and |Σ| = 26 represents the size of the character set (lowercase English letters).

The analysis breaks down as follows:

  • The outer while loop in the main function iterates through the string word once, partitioning it into segments where consecutive characters differ by at most 2. This takes O(n) time total.
  • For each segment, the function f(s) is called, which:
    • Iterates through at most 26 possible values of i (representing 1 to 26 unique characters)
    • For each i, it uses a sliding window of size l = i × k
    • The sliding window traverses the segment once, performing O(1) operations per position (updating counters and frequency maps)
    • Each segment is processed in O(m × 26) where m is the segment length
  • Since the sum of all segment lengths equals n, the total time across all segments is O(n × 26) = O(n × |Σ|)

Space Complexity: O(|Σ|) where |Σ| = 26.

The space usage consists of:

  • cnt: A Counter that stores at most 26 different characters (lowercase letters), requiring O(26) space
  • freq: A Counter that stores frequency counts, with at most 26 different frequency values, requiring O(26) space
  • Other variables use O(1) space
  • The recursive calls and string slicing word[i:j] create new strings, but at most one segment is processed at a time, and the space for the segment is bounded by O(n) in the worst case, but the dominant space usage for the algorithm's working memory is O(|Σ|)

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Incorrect Frequency Counter Updates When Sliding Window

The Pitfall: When sliding the window, developers often update the character count first and then the frequency counter, but forget that the order matters. A common mistake is:

# WRONG: Updates char_count before updating freq counter
char_count[entering_char] += 1
frequency_count[char_count[entering_char]] += 1
frequency_count[char_count[entering_char] - 1] -= 1  # Wrong old frequency

Why It's Wrong: After incrementing char_count[entering_char], you've lost the original frequency value. Trying to decrement the old frequency becomes error-prone.

The Solution: Always update the frequency counter BEFORE modifying the character counter:

# CORRECT: Update frequency counter first
frequency_count[char_count[entering_char]] -= 1  # Remove old frequency
char_count[entering_char] += 1                   # Update character count
frequency_count[char_count[entering_char]] += 1  # Add new frequency

2. Forgetting to Handle Zero Frequencies

The Pitfall: When a character's count becomes 0 (it leaves the window completely), the frequency counter still tracks that there's a character with frequency 0. This can lead to incorrect validation:

# This check might fail even when valid
if frequency_count[k] == num_unique_chars:  # frequency_count[0] might be > 0

The Solution: The current implementation handles this correctly by maintaining the frequency counter properly. When a character count becomes 0, frequency_count[0] increases, but this doesn't affect our check since we only care about frequency_count[k].

3. Off-by-One Error in Window Sliding

The Pitfall: Incorrectly calculating which character is leaving the window:

# WRONG: Off by one
leaving_char = segment[right - window_size + 1]  # Wrong index

# WRONG: Using wrong boundary
for right in range(window_size - 1, segment_length):  # Wrong starting point

The Solution: The leaving character should be at index right - window_size:

# CORRECT
for right in range(window_size, segment_length):
    leaving_char = segment[right - window_size]  # Correct index

4. Not Breaking Early When Window Size Exceeds Segment

The Pitfall: Continuing to check larger window sizes even when they exceed the segment length, leading to unnecessary iterations:

# INEFFICIENT: No early termination
for num_unique_chars in range(1, 27):
    window_size = num_unique_chars * k
    # Continues even when window_size > segment_length

The Solution: Break early when the window size becomes too large:

# EFFICIENT: Early termination
if window_size > segment_length:
    break

5. Misunderstanding the Complete Substring Condition

The Pitfall: Checking if AT LEAST num_unique_chars characters have frequency k, rather than EXACTLY:

# WRONG: Allows more than num_unique_chars distinct characters
if frequency_count[k] >= num_unique_chars:  # Wrong condition

Why It's Wrong: If we have a window of size 3k (expecting 3 unique chars), but 4 different characters appear with some having frequency k, this would incorrectly count as valid.

The Solution: Use strict equality to ensure EXACTLY the expected number of unique characters:

# CORRECT: Exactly num_unique_chars characters must have frequency k
if frequency_count[k] == num_unique_chars:

This works because if the window has size num_unique_chars * k and exactly num_unique_chars characters have frequency k, then these must be the only characters in the window (no room for other characters).

Discover Your Strengths and Weaknesses: Take Our 3-Minute Quiz to Tailor Your Study Plan:

What does the following code do?

1def f(arr1, arr2):
2  i, j = 0, 0
3  new_arr = []
4  while i < len(arr1) and j < len(arr2):
5      if arr1[i] < arr2[j]:
6          new_arr.append(arr1[i])
7          i += 1
8      else:
9          new_arr.append(arr2[j])
10          j += 1
11  new_arr.extend(arr1[i:])
12  new_arr.extend(arr2[j:])
13  return new_arr
14
1public static List<Integer> f(int[] arr1, int[] arr2) {
2  int i = 0, j = 0;
3  List<Integer> newArr = new ArrayList<>();
4
5  while (i < arr1.length && j < arr2.length) {
6      if (arr1[i] < arr2[j]) {
7          newArr.add(arr1[i]);
8          i++;
9      } else {
10          newArr.add(arr2[j]);
11          j++;
12      }
13  }
14
15  while (i < arr1.length) {
16      newArr.add(arr1[i]);
17      i++;
18  }
19
20  while (j < arr2.length) {
21      newArr.add(arr2[j]);
22      j++;
23  }
24
25  return newArr;
26}
27
1function f(arr1, arr2) {
2  let i = 0, j = 0;
3  let newArr = [];
4  
5  while (i < arr1.length && j < arr2.length) {
6      if (arr1[i] < arr2[j]) {
7          newArr.push(arr1[i]);
8          i++;
9      } else {
10          newArr.push(arr2[j]);
11          j++;
12      }
13  }
14  
15  while (i < arr1.length) {
16      newArr.push(arr1[i]);
17      i++;
18  }
19  
20  while (j < arr2.length) {
21      newArr.push(arr2[j]);
22      j++;
23  }
24  
25  return newArr;
26}
27

Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More