githubEdit

05. Longest Substring with K Uniques

βœ… GFG solution to Longest Substring with K Uniques: find longest substring with exactly k distinct characters using sliding window technique. πŸš€

The problem can be found at the following link: πŸ”— Question Linkarrow-up-right

🧩 Problem Description

You are given a string s consisting only of lowercase alphabets and an integer k. Your task is to find the length of the longest substring that contains exactly k distinct characters.

Note: If no such substring exists, return -1.

πŸ“˜ Examples

Example 1

Input: s = "aabacbebebe", k = 3
Output: 7
Explanation: The longest substring with exactly 3 distinct characters is "cbebebe", 
which includes 'c', 'b', and 'e'.

Example 2

Input: s = "aaaa", k = 2
Output: -1
Explanation: There's no substring with 2 distinct characters.

Example 3

πŸ”’ Constraints

  • $1 \le \text{s.size()} \le 10^5$

  • $1 \le k \le 26$

βœ… My Approach

The optimal solution uses Sliding Window with Hash Map:

Sliding Window Strategy

  1. Key Insight:

    • Use two pointers to maintain a window of characters.

    • Track distinct character count in current window.

    • Expand window when distinct count < k, contract when > k.

  2. Hash Map Usage:

    • Store character frequencies in the current window.

    • Map size gives count of distinct characters.

    • Remove characters when frequency becomes 0.

  3. Window Management:

    • Expand: Add character at right pointer to map.

    • Contract: Remove character at left pointer from map.

    • Update result only when distinct count equals exactly k.

  4. Algorithm Steps:

    • Initialize left and right pointers at 0.

    • Expand window by moving right pointer.

    • If distinct count > k, shrink from left.

    • Track maximum length when distinct count == k.

    • Return -1 if no valid substring found.

Why This Works: The sliding window ensures we check all possible substrings efficiently while maintaining exactly k distinct characters through dynamic expansion and contraction.

πŸ“ Time and Auxiliary Space Complexity

  • Expected Time Complexity: O(n), where n is the length of the string. Each character is visited at most twice (once by right pointer during expansion and once by left pointer during contraction).

  • Expected Auxiliary Space Complexity: O(k), where k is the number of distinct characters allowed. In the worst case, the hash map stores at most k+1 characters (when we're about to shrink the window), which is O(k) space.

πŸ§‘β€πŸ’» Code (C++)

chevron-right⚑ View Alternative Approaches with Code and Analysishashtag

πŸ“Š 2️⃣ Frequency Array Approach

πŸ’‘ Algorithm Steps:

  1. Use array of size 26 to track character frequencies.

  2. Maintain count of distinct characters separately.

  3. Expand window and update frequency array.

  4. Contract window when distinct count exceeds k.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n) - Linear traversal with constant time operations

  • Auxiliary Space: πŸ’Ύ O(1) - Fixed size array of 26 elements

βœ… Why This Approach?

  • Space efficient with fixed array size

  • Faster access than hash map (array indexing)

  • Good for lowercase letters only

πŸ“Š 3️⃣ Brute Force Approach

πŸ’‘ Algorithm Steps:

  1. Try all possible substrings starting from each position.

  2. For each substring, count distinct characters using a set.

  3. If distinct count equals k, update maximum length.

  4. Return maximum length found or -1.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(nΒ²) - Nested loops for all substrings

  • Auxiliary Space: πŸ’Ύ O(k) - Set size bounded by k

βœ… Why This Approach?

  • Simple and straightforward

  • Easy to understand and debug

  • Good for small strings

πŸ“Š 4️⃣ Optimized Map with Early Termination

πŸ’‘ Algorithm Steps:

  1. Check if string has at least k distinct characters first.

  2. If not, return -1 immediately.

  3. Apply sliding window with hash map.

  4. Track maximum when window has exactly k distinct chars.

πŸ“ Complexity Analysis:

  • Time: ⏱️ O(n) - Linear with early termination check

  • Auxiliary Space: πŸ’Ύ O(k) - Map and set storage

βœ… Why This Approach?

  • Early termination saves time for invalid cases

  • Optimized for cases where k > distinct chars

  • Clear validation before processing

πŸ†š πŸ” Comparison of Approaches

πŸš€ Approach

⏱️ Time Complexity

πŸ’Ύ Space Complexity

βœ… Pros

⚠️ Cons

🎯 Hash Map Sliding

🟒 O(n)

🟑 O(k)

πŸš€ Flexible, handles any chars

πŸ”§ Hash map overhead

πŸ“Š Frequency Array

🟒 O(n)

🟒 O(1)

⚑ Fastest, constant space

πŸ”§ Limited to lowercase only

πŸ”„ Brute Force

πŸ”΄ O(nΒ²)

🟑 O(k)

πŸ“– Simple to understand

🐌 Quadratic time

πŸ” Early Termination

🟒 O(n)

🟑 O(k)

🎯 Optimized for invalid cases

πŸ”§ Extra initial check

πŸ† Best Choice Recommendation

🎯 Scenario

πŸŽ–οΈ Recommended Approach

πŸ”₯ Performance Rating

πŸ… General case, any characters

πŸ₯‡ Hash Map Sliding

β˜…β˜…β˜…β˜…β˜…

⚑ Lowercase only, max performance

πŸ₯ˆ Frequency Array

β˜…β˜…β˜…β˜…β˜…

πŸ“– Learning/Understanding

πŸ₯‰ Brute Force

β˜…β˜…β˜…β˜†β˜†

🎯 Many invalid inputs expected

πŸ… Early Termination

β˜…β˜…β˜…β˜…β˜†

β˜• Code (Java)

🐍 Code (Python)

🧠 Contribution and Support

For discussions, questions, or doubts related to this solution, feel free to connect on LinkedIn: πŸ“¬ Any Questions?arrow-up-right. Let's make this learning journey more collaborative!

⭐ If you find this helpful, please give this repository a star! ⭐


πŸ“Visitor Count

Visitor counter

Last updated