Skip to content
geeksforgeeks
  • Courses
    • DSA to Development
    • Get IBM Certification
    • Newly Launched!
      • Master Django Framework
      • Become AWS Certified
    • For Working Professionals
      • Interview 101: DSA & System Design
      • Data Science Training Program
      • JAVA Backend Development (Live)
      • DevOps Engineering (LIVE)
      • Data Structures & Algorithms in Python
    • For Students
      • Placement Preparation Course
      • Data Science (Live)
      • Data Structure & Algorithm-Self Paced (C++/JAVA)
      • Master Competitive Programming (Live)
      • Full Stack Development with React & Node JS (Live)
    • Full Stack Development
    • Data Science Program
    • All Courses
  • Tutorials
    • Data Structures & Algorithms
    • ML & Data Science
    • Interview Corner
    • Programming Languages
    • Web Development
    • CS Subjects
    • DevOps And Linux
    • School Learning
  • Practice
    • Build your AI Agent
    • GfG 160
    • Problem of the Day
    • Practice Coding Problems
    • GfG SDE Sheet
  • Contests
    • Accenture Hackathon (Ending Soon!)
    • GfG Weekly [Rated Contest]
    • Job-A-Thon Hiring Challenge
    • All Contests and Events
  • DSA
  • Practice Searching Algorithms
  • MCQs on Searching Algorithms
  • Tutorial on Searching Algorithms
  • Linear Search
  • Binary Search
  • Ternary Search
  • Jump Search
  • Sentinel Linear Search
  • Interpolation Search
  • Exponential Search
  • Fibonacci Search
  • Ubiquitous Binary Search
  • Linear Search Vs Binary Search
  • Interpolation Search Vs Binary Search
  • Binary Search Vs Ternary Search
  • Sentinel Linear Search Vs Linear Search
Open In App
Next Article:
Largest substring with same Characters
Next article icon

Longest substring with K unique characters using Binary Search

Last Updated : 25 Apr, 2023
Comments
Improve
Suggest changes
Like Article
Like
Report

Given a string str and an integer K, the task is to print the length of the longest possible substring that has exactly K unique characters. If there is more than one substring of the longest possible length, then print any one of them or print -1 if there is no such substring possible.

Examples: 

Input: str = “aabacbebebe”, K = 3 
Output: 7 
“cbebebe” is the required substring.

Input: str = “aabc”, K = 4 
Output: -1 

Recommended: Please try your approach on {IDE} first, before moving on to the solution.
 

Approach: An approach to solve this problem has been discussed in this article. In this article, a binary search based approach will be discussed. Binary search will be applied to the length of the substring which has at least K unique characters. Let’s say we try for length len and check whether a substring of size len is there which is having at least k unique characters. If it is possible, then try to maximize the size by searching for this length to the maximum possible length, i.e. the size of the input string. If it is not possible, then search for a lower size len. 
To check that the length given by binary search will have k unique characters, a set can be used to insert all the characters, and then if the size of the set is less than k then the answer is not possible, else the answer given by the binary search is the max answer. 
Binary search is applicable here because it is known if for some len the answer is possible and we want to maximize the len so the search domain changes and we search from this len to n.
Below is the implementation of the above approach:

C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function that returns true if there
// is a substring of length len
// with <=k unique characters
bool isValidLen(string s, int len, int k)
{
 
    // Size of the string
    int n = s.size();
 
    // Map to store the characters
    // and their frequency
    unordered_map<char, int> mp;
    int right = 0;
 
    // Update the map for the
    // first substring
    while (right < len) {
        mp[s[right]]++;
        right++;
    }
 
    if (mp.size() <= k)
        return true;
 
    // Check for the rest of the substrings
    while (right < n) {
 
        // Add the new character
        mp[s[right]]++;
 
        // Remove the first character
        // of the previous window
        mp[s[right - len]]--;
 
        // Update the map
        if (mp[s[right - len]] == 0)
            mp.erase(s[right - len]);
        if (mp.size() <= k)
            return true;
        right++;
    }
    return mp.size() <= k;
}
 
// Function to return the length of the
// longest substring which has K
// unique characters
int maxLenSubStr(string s, int k)
{
 
    // Check if the complete string
    // contains K unique characters
    set<char> uni;
    for (auto x : s)
        uni.insert(x);
    if (uni.size() < k)
        return -1;
 
    // Size of the string
    int n = s.size();
 
    // Apply binary search
    int lo = -1, hi = n + 1;
    while (hi - lo > 1) {
        int mid = lo + hi >> 1;
        if (isValidLen(s, mid, k))
            lo = mid;
        else
            hi = mid;
    }
    return lo;
}
 
// Driver code
int main()
{
    string s = "aabacbebebe";
    int k = 3;
 
    cout << maxLenSubStr(s, k);
 
    return 0;
}
 
 

Java




// Java implementation of the approach
import java.util.*;
 
class GFG
{
 
    // Function that returns true if there
    // is a subString of length len
    // with <=k unique characters
    static boolean isValidLen(String s,
                              int len, int k)
    {
 
        // Size of the String
        int n = s.length();
 
        // Map to store the characters
        // and their frequency
        Map<Character,
            Integer> mp = new HashMap<Character,
                                      Integer>();
        int right = 0;
 
        // Update the map for the
        // first subString
        while (right < len)
        {
            if (mp.containsKey(s.charAt(right)))
            {
                mp.put(s.charAt(right),
                mp.get(s.charAt(right)) + 1);
            }
            else
            {
                mp.put(s.charAt(right), 1);
            }
            right++;
        }
 
        if (mp.size() <= k)
            return true;
 
        // Check for the rest of the subStrings
        while (right < n)
        {
 
            // Add the new character
            if (mp.containsKey(s.charAt(right)))
            {
                mp.put(s.charAt(right),
                mp.get(s.charAt(right)) + 1);
            }
            else
            {
                mp.put(s.charAt(right), 1);
            }
 
            // Remove the first character
            // of the previous window
            if (mp.containsKey(s.charAt(right - len)))
            {
                mp.put(s.charAt(right - len),
                mp.get(s.charAt(right - len)) - 1);
            }
 
            // Update the map
            if (mp.get(s.charAt(right - len)) == 0)
                mp.remove(s.charAt(right - len));
            if (mp.size() <= k)
                return true;
            right++;
        }
        return mp.size() <= k;
    }
 
    // Function to return the length of the
    // longest subString which has K
    // unique characters
    static int maxLenSubStr(String s, int k)
    {
 
        // Check if the complete String
        // contains K unique characters
        Set<Character> uni = new HashSet<Character>();
        for (Character x : s.toCharArray())
            uni.add(x);
        if (uni.size() < k)
            return -1;
 
        // Size of the String
        int n = s.length();
 
        // Apply binary search
        int lo = -1, hi = n + 1;
        while (hi - lo > 1)
        {
            int mid = lo + hi >> 1;
            if (isValidLen(s, mid, k))
                lo = mid;
            else
                hi = mid;
        }
        return lo;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        String s = "aabacbebebe";
        int k = 3;
 
        System.out.print(maxLenSubStr(s, k));
    }
}
 
// This code is contributed by Rajput-Ji
 
 

Python3




# Python3 implementation of the approach
 
# Function that returns True if there
# is a sub of length len
# with <=k unique characters
def isValidLen(s, lenn, k):
 
    # Size of the
    n = len(s)
 
    # Map to store the characters
    # and their frequency
    mp = dict()
    right = 0
 
    # Update the map for the
    # first sub
    while (right < lenn):
        mp[s[right]] = mp.get(s[right], 0) + 1
        right += 1
 
    if (len(mp) <= k):
        return True
 
    # Check for the rest of the subs
    while (right < n):
 
        # Add the new character
        mp[s[right]] = mp.get(s[right], 0) + 1
 
        # Remove the first character
        # of the previous window
        mp[s[right - lenn]] -= 1
 
        # Update the map
        if (mp[s[right - lenn]] == 0):
            del mp[s[right - lenn]]
        if (len(mp) <= k):
            return True
        right += 1
 
    return len(mp)<= k
 
# Function to return the length of the
# longest sub which has K
# unique characters
def maxLenSubStr(s, k):
 
    # Check if the complete
    # contains K unique characters
    uni = dict()
    for x in s:
        uni[x] = 1
    if (len(uni) < k):
        return -1
 
    # Size of the
    n = len(s)
 
    # Apply binary search
    lo = -1
    hi = n + 1
    while (hi - lo > 1):
        mid = lo + hi >> 1
        if (isValidLen(s, mid, k)):
            lo = mid
        else:
            hi = mid
 
    return lo
 
# Driver code
s = "aabacbebebe"
k = 3
 
print(maxLenSubStr(s, k))
 
# This code is contributed by Mohit Kumar
 
 

C#




// C# implementation of the approach
using System;
using System.Collections.Generic;
 
class GFG
{
 
    // Function that returns true if there
    // is a subString of length len
    // with <=k unique characters
    static bool isValidLen(String s,
                           int len, int k)
    {
 
        // Size of the String
        int n = s.Length;
 
        // Map to store the characters
        // and their frequency
        Dictionary<char,
                   int> mp = new Dictionary<char,
                                            int>();
        int right = 0;
 
        // Update the map for the
        // first subString
        while (right < len)
        {
            if (mp.ContainsKey(s[right]))
            {
                mp[s[right]] = mp[s[right]] + 1;
            }
            else
            {
                mp.Add(s[right], 1);
            }
            right++;
        }
 
        if (mp.Count <= k)
            return true;
 
        // Check for the rest of the subStrings
        while (right < n)
        {
 
            // Add the new character
            if (mp.ContainsKey(s[right]))
            {
                mp[s[right]] = mp[s[right]] + 1;
            }
            else
            {
                mp.Add(s[right], 1);
            }
 
            // Remove the first character
            // of the previous window
            if (mp.ContainsKey(s[right - len]))
            {
                mp[s[right - len]] = mp[s[right - len]] - 1;
            }
 
            // Update the map
            if (mp[s[right - len]] == 0)
                mp.Remove(s[right - len]);
            if (mp.Count <= k)
                return true;
            right++;
        }
        return mp.Count <= k;
    }
 
    // Function to return the length of the
    // longest subString which has K
    // unique characters
    static int maxLenSubStr(String s, int k)
    {
 
        // Check if the complete String
        // contains K unique characters
        HashSet<char> uni = new HashSet<char>();
        foreach (char x in s.ToCharArray())
            uni.Add(x);
        if (uni.Count < k)
            return -1;
 
        // Size of the String
        int n = s.Length;
 
        // Apply binary search
        int lo = -1, hi = n + 1;
        while (hi - lo > 1)
        {
            int mid = lo + hi >> 1;
            if (isValidLen(s, mid, k))
                lo = mid;
            else
                hi = mid;
        }
        return lo;
    }
 
    // Driver code
    public static void Main(String[] args)
    {
        String s = "aabacbebebe";
        int k = 3;
 
        Console.Write(maxLenSubStr(s, k));
    }
}
 
// This code is contributed by Rajput-Ji
 
 

Javascript




<script>
  
// Javascript implementation of the approach
 
// Function that returns true if there
// is a substring of length len
// with <=k unique characters
function isValidLen(s, len, k)
{
 
    // Size of the string
    var n = s.length;
 
    // Map to store the characters
    // and their frequency
    var mp = new Map();
    var right = 0;
 
    // Update the map for the
    // first substring
    while (right < len) {
        if(mp.has(s[right]))
            mp.set(s[right],mp.get(s[right])+1)
        else
            mp.set(s[right], 1)
        right++;
    }
 
    if (mp.size <= k)
        return true;
 
    // Check for the rest of the substrings
    while (right < n) {
 
        // Add the new character
        if(mp.has(s[right]))
            mp.set(s[right],mp.get(s[right])+1)
        else
            mp.set(s[right], 1)
 
        // Remove the first character
        // of the previous window
        if(mp.has(s[right - len]))
            mp.set(s[right - len], mp.get(s[right - len])-1)
 
        // Update the map
        if(mp.has(s[right - len]) && mp.get(s[right - len])==0)
            mp.delete(s[right - len]);
        if (mp.size <= k)
            return true;
        right++;
    }
    return mp.size <= k;
}
 
// Function to return the length of the
// longest substring which has K
// unique characters
function maxLenSubStr(s, k)
{
 
    // Check if the complete string
    // contains K unique characters
    var uni = new Set();
    s.split('').forEach(x => {
        uni.add(x);
    });
     
    if (uni.size < k)
        return -1;
 
    // Size of the string
    var n = s.length;
 
    // Apply binary search
    var lo = -1, hi = n + 1;
    while (hi - lo > 1) {
        var mid = lo + hi >> 1;
        if (isValidLen(s, mid, k))
            lo = mid;
        else
            hi = mid;
    }
    return lo;
}
 
// Driver code
var s = "aabacbebebe";
var k = 3;
document.write( maxLenSubStr(s, k));
 
</script>
 
 
Output: 
7

 

The time complexity of the given program is O(N*logN), where N is the length of the input string. This is because the program uses binary search to find the maximum length of a substring with K unique characters, and the isValidLen function checks whether a substring of a given length has at most K unique characters.

The space complexity of the given program is O(N), where N is the length of the input string. This is because the program uses an unordered_map to keep track of the frequency of each character in the current substring, and the size of this map can be at most the number of unique characters in the input string, which is O(N) in the worst case. Additionally, the program uses a set to check whether the input string contains at least K unique characters, and the size of this set can also be at most O(N).
 



Next Article
Largest substring with same Characters

D

Dwngu
Improve
Article Tags :
  • C++
  • DSA
  • Searching
  • Strings
  • Binary Search
  • substring
Practice Tags :
  • CPP
  • Binary Search
  • Searching
  • Strings

Similar Reads

  • Longest substring with k unique characters
    Given a string you need to print longest possible substring that has exactly k unique characters. If there is more than one substring of longest possible length, then print any one of them. Note:- Source(Google Interview Question). Examples: Input: Str = "aabbcc", k = 1Output: 2Explanation: Max subs
    13 min read
  • Longest substring consisting of vowels using Binary Search
    Given string str of length N, the task is to find the longest substring which contains only vowels using the Binary Search technique.Examples: Input: str = "baeicba" Output: 3 Explanation: Longest substring which contains vowels only is "aei".Input: str = "aeiou" Output: 5 Approach: Refer to the Lon
    8 min read
  • Largest substring with same Characters
    Given a string s of size N. The task is to find the largest substring which consists of the same charactersExamples: Input : s = "abcdddddeff" Output : 5 Substring is "ddddd"Input : s = aabceebeee Output : 3 Approach : Traverse through the string from left to right. Take two variables ans and temp.
    4 min read
  • Longest Substring Without Repeating Characters
    Given a string s having lowercase characters, find the length of the longest substring without repeating characters. Examples: Input: s = "geeksforgeeks"Output: 7 Explanation: The longest substrings without repeating characters are "eksforg” and "ksforge", with lengths of 7. Input: s = "aaa"Output:
    12 min read
  • Find the Longest Common Substring using Binary search and Rolling Hash
    Given two strings X and Y, the task is to find the length of the longest common substring. Examples: Input: X = “GeeksforGeeks”, y = “GeeksQuiz” Output: 5 Explanation: The longest common substring is “Geeks” and is of length 5. Input: X = “abcdxyz”, y = “xyzabcd” Output: 4 Explanation: The longest c
    11 min read
  • Longest substring where all the characters appear at least K times | Set 3
    Given a string str and an integer K, the task is to find the length of the longest substring S such that every character in S appears at least K times. Examples: Input: str = “aabbba”, K = 3Output: 6Explanation: In substring "aabbba", each character repeats at least k times and its length is 6. Inpu
    12 min read
  • Find minimum number of Substrings with unique characters
    Given string 's', the task is to divide a given string s into multiple substrings, with each substring containing only unique characters. This means that no character should be repeated within a single substring. The goal is to find the minimum number of such substrings required to satisfy this cond
    12 min read
  • Longest substring with atmost K characters from the given set of characters
    Given a string S, an integer K and set of characters Q[], the task is to find the longest substring in string S which contains atmost K characters from the given character set Q[].Examples: Input: S = "normal", Q = {"a", "o", "n", "m", "r", "l"}, K = 1 Output: 1Explanation: All the characters in the
    9 min read
  • Find length of longest substring with at most K normal characters
    Given a string P consisting of small English letters and a 26-digit bit string Q, where 1 represents the special character and 0 represents a normal character for the 26 English alphabets. The task is to find the length of the longest substring with at most K normal characters. Examples: Input : P =
    12 min read
  • Print Longest substring without repeating characters
    Given a string s having lowercase characters, find the length of the longest substring without repeating characters. Examples: Input: s = “geeksforgeeks”Output: 7 Explanation: The longest substrings without repeating characters are “eksforg” and “ksforge”, with lengths of 7. Input: s = “aaa”Output:
    14 min read
geeksforgeeks-footer-logo
Corporate & Communications Address:
A-143, 7th Floor, Sovereign Corporate Tower, Sector- 136, Noida, Uttar Pradesh (201305)
Registered Address:
K 061, Tower K, Gulshan Vivante Apartment, Sector 137, Noida, Gautam Buddh Nagar, Uttar Pradesh, 201305
GFG App on Play Store GFG App on App Store
Advertise with us
  • Company
  • About Us
  • Legal
  • Privacy Policy
  • In Media
  • Contact Us
  • Advertise with us
  • GFG Corporate Solution
  • Placement Training Program
  • Languages
  • Python
  • Java
  • C++
  • PHP
  • GoLang
  • SQL
  • R Language
  • Android Tutorial
  • Tutorials Archive
  • DSA
  • Data Structures
  • Algorithms
  • DSA for Beginners
  • Basic DSA Problems
  • DSA Roadmap
  • Top 100 DSA Interview Problems
  • DSA Roadmap by Sandeep Jain
  • All Cheat Sheets
  • Data Science & ML
  • Data Science With Python
  • Data Science For Beginner
  • Machine Learning
  • ML Maths
  • Data Visualisation
  • Pandas
  • NumPy
  • NLP
  • Deep Learning
  • Web Technologies
  • HTML
  • CSS
  • JavaScript
  • TypeScript
  • ReactJS
  • NextJS
  • Bootstrap
  • Web Design
  • Python Tutorial
  • Python Programming Examples
  • Python Projects
  • Python Tkinter
  • Python Web Scraping
  • OpenCV Tutorial
  • Python Interview Question
  • Django
  • Computer Science
  • Operating Systems
  • Computer Network
  • Database Management System
  • Software Engineering
  • Digital Logic Design
  • Engineering Maths
  • Software Development
  • Software Testing
  • DevOps
  • Git
  • Linux
  • AWS
  • Docker
  • Kubernetes
  • Azure
  • GCP
  • DevOps Roadmap
  • System Design
  • High Level Design
  • Low Level Design
  • UML Diagrams
  • Interview Guide
  • Design Patterns
  • OOAD
  • System Design Bootcamp
  • Interview Questions
  • Inteview Preparation
  • Competitive Programming
  • Top DS or Algo for CP
  • Company-Wise Recruitment Process
  • Company-Wise Preparation
  • Aptitude Preparation
  • Puzzles
  • School Subjects
  • Mathematics
  • Physics
  • Chemistry
  • Biology
  • Social Science
  • English Grammar
  • Commerce
  • World GK
  • GeeksforGeeks Videos
  • DSA
  • Python
  • Java
  • C++
  • Web Development
  • Data Science
  • CS Subjects
@GeeksforGeeks, Sanchhaya Education Private Limited, All rights reserved
We use cookies to ensure you have the best browsing experience on our website. By using our site, you acknowledge that you have read and understood our Cookie Policy & Privacy Policy
Lightbox
Improvement
Suggest Changes
Help us improve. Share your suggestions to enhance the article. Contribute your expertise and make a difference in the GeeksforGeeks portal.
geeksforgeeks-suggest-icon
Create Improvement
Enhance the article with your expertise. Contribute to the GeeksforGeeks community and help create better learning resources for all.
geeksforgeeks-improvement-icon
Suggest Changes
min 4 words, max Words Limit:1000

Thank You!

Your suggestions are valuable to us.

What kind of Experience do you want to share?

Interview Experiences
Admission Experiences
Career Journeys
Work Experiences
Campus Experiences
Competitive Exam Experiences