Open In App

Lexicographically smallest K-length subsequence from a given string

Last Updated : 06 May, 2025
Summarize
Comments
Improve
Suggest changes
Share
Like Article
Like
Report

Given a string s of length n, the task is to find the lexicographically smallest k-length subsequence from the string s (where k < n). 

Examples:

Input: s = "bbcaab", k = 3
Output: "aab"

Input: s = "aabdaabc", k = 3
Output: "aaa"

[Naive Approach] Generating all Subsequences - O(2^n) time and O(C(n,k)*k+n) space

The idea is to generate all possible subsequences of length k from the input string s, store them in an array, sort them lexicographically, and return the first (smallest) string.

C++
// C++ program to find Lexicographically smallest 
// K-length subsequence from a given string
#include <bits/stdc++.h>
using namespace std;

// Recursive function to generate all subsequences of length k
void generateSub(string s, int i, int k, string curr, 
vector<string>& result) {
    int n = s.length();
    
    // If we've reached end of string and string 
    // is of length k.
    if (i == n) {
        if (curr.length() == k) result.push_back(curr);
        return;
    }
    
    // Include curr character
    generateSub(s, i + 1, k, curr + s[i], result);
    
    // Exclude curr character
    generateSub(s, i + 1, k, curr, result);
}

string lexSmallest(string s, int k) {
    int n = s.length();
    
    vector<string> subsequences;
    generateSub(s, 0, k, "", subsequences);
    
    // Sort all subsequences lexicographically
    sort(subsequences.begin(), subsequences.end());
    
    // Return the lexicographically smallest subsequence
    return subsequences[0];
}

int main() {
    string s = "bbcaab";
    int k = 3;
    cout << lexSmallest(s, k);
    
    return 0;
}
Java
// Java program to find Lexicographically smallest 
// K-length subsequence from a given string

import java.util.*;

class GfG {

    // Recursive function to generate all subsequences of length k
    static void generateSub(String s, int i, int k, 
    String curr, ArrayList<String> result) {
        int n = s.length();

        // If we've reached end of string and string 
        // is of length k.
        if (i == n) {
            if (curr.length() == k) result.add(curr);
            return;
        }

        // Include curr character
        generateSub(s, i + 1, k, curr + s.charAt(i), result);

        // Exclude curr character
        generateSub(s, i + 1, k, curr, result);
    }

    static String lexSmallest(String s, int k) {
        int n = s.length();

        ArrayList<String> subsequences = new ArrayList<>();
        generateSub(s, 0, k, "", subsequences);

        // Sort all subsequences lexicographically
        Collections.sort(subsequences);

        // Return the lexicographically smallest subsequence
        return subsequences.get(0);
    }

    public static void main(String[] args) {
        String s = "bbcaab";
        int k = 3;
        System.out.println(lexSmallest(s, k));
    }
}
Python
# Python program to find Lexicographically smallest 
# K-length subsequence from a given string

# Recursive function to generate all subsequences of length k
def generateSub(s, i, k, curr, result):
    n = len(s)

    # If we've reached end of string and string 
    # is of length k.
    if i == n:
        if len(curr) == k:
            result.append(curr)
        return

    # Include curr character
    generateSub(s, i + 1, k, curr + s[i], result)

    # Exclude curr character
    generateSub(s, i + 1, k, curr, result)

def lexSmallest(s, k):
    n = len(s)

    subsequences = []
    generateSub(s, 0, k, "", subsequences)

    # Sort all subsequences lexicographically
    subsequences.sort()

    # Return the lexicographically smallest subsequence
    return subsequences[0]

if __name__ == "__main__":
    s = "bbcaab"
    k = 3
    print(lexSmallest(s, k))
C#
// C# program to find Lexicographically smallest 
// K-length subsequence from a given string

using System;
using System.Collections.Generic;

class GfG {

    // Recursive function to generate all subsequences of length k
    static void generateSub(string s, int i, int k, 
    string curr, List<string> result) {
        int n = s.Length;

        // If we've reached end of string and string 
        // is of length k.
        if (i == n) {
            if (curr.Length == k) result.Add(curr);
            return;
        }

        // Include curr character
        generateSub(s, i + 1, k, curr + s[i], result);

        // Exclude curr character
        generateSub(s, i + 1, k, curr, result);
    }

    static string lexSmallest(string s, int k) {
        int n = s.Length;

        List<string> subsequences = new List<string>();
        generateSub(s, 0, k, "", subsequences);

        // Sort all subsequences lexicographically
        subsequences.Sort();

        // Return the lexicographically smallest subsequence
        return subsequences[0];
    }

    static void Main(string[] args) {
        string s = "bbcaab";
        int k = 3;
        Console.WriteLine(lexSmallest(s, k));
    }
}
JavaScript
// JavaScript program to find Lexicographically smallest 
// K-length subsequence from a given string

// Recursive function to generate all subsequences of length k
function generateSub(s, i, k, curr, result) {
    let n = s.length;

    // If we've reached end of string and string 
    // is of length k.
    if (i === n) {
        if (curr.length === k) result.push(curr);
        return;
    }

    // Include curr character
    generateSub(s, i + 1, k, curr + s[i], result);

    // Exclude curr character
    generateSub(s, i + 1, k, curr, result);
}

function lexSmallest(s, k) {
    let n = s.length;

    let subsequences = [];
    generateSub(s, 0, k, "", subsequences);

    // Sort all subsequences lexicographically
    subsequences.sort();

    // Return the lexicographically smallest subsequence
    return subsequences[0];
}

let s = "bbcaab";
let k = 3;
console.log(lexSmallest(s, k));

Output
aab

Time Complexity: O(2^n), at each index we have two choices: include the character or exclude it.
Auxiliary Space: O(C(n,k)*k + n), where C(n,k) equals the number of subsequences of length k, which can be created from a string of length n.

[Expected Approach] Using Stack - O(n) time and O(n) space

We use a stack that maintain the result so far. We process each character of the string from left to right, always maintaining the lexicographically smallest subsequence of the appropriate length seen so far. Whenever we encounter a smaller character than top of the stack, we remove larger characters to ensure the smallest possible subsequence, also ensuring we'll still have enough remaining characters to form a subsequence of length k.

Step by step approach:

  1. Process each character from left to right, maintaining a stack of the best possible subsequence.
  2. Pop characters from the stack when a smaller one is found and we have enough remaining characters.
  3. Add the current character to the stack only if we haven't collected k characters yet.
  4. Build the final result by emptying the stack and reversing the characters.
C++
// C++ program to find Lexicographically smallest 
// K-length subsequence from a given string
#include <bits/stdc++.h>
using namespace std;

string lexSmallest(string s, int k) {
    int n = s.length();
    
    stack<char> st;
    
    for (int i=0; i<n; i++) {
        
        // While stack is not empty, and top 
        // of stack is less than current char 
        // while ensuring there are enough 
        // characters left to make subsequence
        // of length k.
        while (!st.empty() && st.top()>s[i] && st.size()-1+n-i >= k) {
            st.pop();
        }
        
        // If size of stack is less than k.
        if (st.size() < k) st.push(s[i]);
    }
    
    string res = "";
    while (!st.empty()) {
        res += st.top();
        st.pop();
    }
    
    // Reverse the string to get the 
    // final resultant string
    reverse(res.begin(), res.end());
    
    return res;
}

int main() {
    string s = "bbcaab";
    int k = 3;
    cout << lexSmallest(s, k);
    
    return 0;
}
Java
// Java program to find Lexicographically smallest 
// K-length subsequence from a given string

import java.util.*;

class GfG {

    static String lexSmallest(String s, int k) {
        int n = s.length();

        Stack<Character> st = new Stack<>();

        for (int i = 0; i < n; i++) {

            // While stack is not empty, and top 
            // of stack is less than current char 
            // while ensuring there are enough 
            // characters left to make subsequence
            // of length k.
            while (!st.isEmpty() && st.peek() > s.charAt(i) 
            && st.size() - 1 + n - i >= k) {
                st.pop();
            }

            // If size of stack is less than k.
            if (st.size() < k) st.push(s.charAt(i));
        }

        StringBuilder res = new StringBuilder();
        while (!st.isEmpty()) {
            res.append(st.pop());
        }

        // Reverse the string to get the 
        // final resultant string
        res.reverse();

        return res.toString();
    }

    public static void main(String[] args) {
        String s = "bbcaab";
        int k = 3;
        System.out.println(lexSmallest(s, k));
    }
}
Python
# Python program to find Lexicographically smallest 
# K-length subsequence from a given string

def lexSmallest(s, k):
    n = len(s)

    st = []

    for i in range(n):

        # While stack is not empty, and top 
        # of stack is less than current char 
        # while ensuring there are enough 
        # characters left to make subsequence
        # of length k.
        while st and st[-1] > s[i] and len(st) - 1 + n - i >= k:
            st.pop()

        # If size of stack is less than k.
        if len(st) < k:
            st.append(s[i])

    res = ""
    while st:
        res += st.pop()

    # Reverse the string to get the 
    # final resultant string
    res = res[::-1]

    return res

if __name__ == "__main__":
    s = "bbcaab"
    k = 3
    print(lexSmallest(s, k))
C#
// C# program to find Lexicographically smallest 
// K-length subsequence from a given string

using System;
using System.Collections.Generic;
using System.Text;

class GfG {

    static string lexSmallest(string s, int k) {
        int n = s.Length;

        Stack<char> st = new Stack<char>();

        for (int i = 0; i < n; i++) {

            // While stack is not empty, and top 
            // of stack is less than current char 
            // while ensuring there are enough 
            // characters left to make subsequence
            // of length k.
            while (st.Count > 0 && st.Peek() > s[i] && 
            st.Count - 1 + n - i >= k) {
                st.Pop();
            }

            // If size of stack is less than k.
            if (st.Count < k) st.Push(s[i]);
        }

        StringBuilder res = new StringBuilder();
        while (st.Count > 0) {
            res.Append(st.Pop());
        }

        // Reverse the string to get the 
        // final resultant string
        char[] arr = res.ToString().ToCharArray();
        Array.Reverse(arr);
        return new string(arr);
    }

    static void Main(string[] args) {
        string s = "bbcaab";
        int k = 3;
        Console.WriteLine(lexSmallest(s, k));
    }
}
JavaScript
// JavaScript program to find Lexicographically smallest 
// K-length subsequence from a given string

function lexSmallest(s, k) {
    let n = s.length;

    let st = [];

    for (let i = 0; i < n; i++) {

        // While stack is not empty, and top 
        // of stack is less than current char 
        // while ensuring there are enough 
        // characters left to make subsequence
        // of length k.
        while (st.length > 0 && st[st.length - 1] > s[i] 
        && st.length - 1 + n - i >= k) {
            st.pop();
        }

        // If size of stack is less than k.
        if (st.length < k) st.push(s[i]);
    }

    let res = "";
    while (st.length > 0) {
        res += st.pop();
    }

    // Reverse the string to get the 
    // final resultant string
    res = res.split("").reverse().join("");

    return res;
}

let s = "bbcaab";
let k = 3;
console.log(lexSmallest(s, k));

Output
aab

Next Article

Similar Reads