Open in App
Not now

Lexicographically smallest String by removing exactly K characters

• Last Updated : 23 Jan, 2023

Given a string S consisting of only lowercase characters, the task is to find the lexicographically smallest string after removing exactly K characters from the string. But you have to modify the value of K, i.e., if the length of the string is a power of 2, reduce K by half, else multiply K by 2. You can remove any K character.

NOTE: If it is not possible to remove K (the value of K after correction) characters or if the resulting string is empty return -1.

Examples:

Input: S = “fooland”, K = 2
Output: “and”
Explanation: As the size of the string = 7, which is not a power of 2, hence K = 4. After removing 4 characters from the given string, the lexicographically smallest string is “and”.

Input: S = “code”, K = 4
Output: “cd”
Explanation: As the length of the string = 4,  which is 2 to the power 2, hence k = 2. Hence, lexicographically smallest string after removal of 2 characters is “cd”.

Naive Approach: The basic way to solve the problem is as follows:

The idea is to find the smallest (n – K) characters from string using nested loop.

Follow the steps to solve this problem:

• First, correct the value of K by checking the length of the string is in the power of 2 or not.
• To check the length of the string is present in the power of 2 or not we can use the count of BitSet in length.
• If the Count of BitSet is 1 that means string_length has only one bit which means it is in the power of 2.
• If the size of the string is in the power of 2 then divide K by 2 else multiply K by 2.
• Now check if K is greater than or equal to the size of the string then return -1.
• Else, Initialize an array of size string_length with 1 for marking all removed(0) and taken(1) elements.
• Run a loop from 0 to the end of string_length
• Run a nested loop inside the upper loop from the upper loop’s index till index + K and find the smallest character between the range.
• Now run a loop from (smallest character index) – 1 till the upper loop index and marks all index with zero – that means it is removed from the string, here we have to count the number of removed characters as well if it is equal to K then stop.
• Set i = (smallest character index) + 1
• When come out of the loop check count of the removed character is less than K then remove that number of characters from the end of the string and mark that index with zero.
• Now run a loop from 0 to string_length and check if the mark of that index is 1 then add the character[i] into the Ans.
• Return the Ans.

Below is the implementation of the above approach.

C++

 `// C++ code to implement the approach`   `#include ` `using` `namespace` `std;`   `// Function to find the setbit count` `int` `countSetBits(``int` `n)` `{` `    ``int` `count = 0;` `    ``while` `(n) {` `        ``count += n & 1;` `        ``n >>= 1;` `    ``}` `    ``return` `count;` `}`   `// Function to find the lexicographically` `// smallest possible string` `string lexicographicallySmallest(string str, ``int` `k)` `{` `    ``int` `n = str.size();`   `    ``// If length is power of 2` `    ``// then divide k by 2` `    ``if` `(countSetBits(n) == 1)` `        ``k /= 2;`   `    ``// Else multiply k with 2` `    ``else` `        ``k *= 2;`   `    ``// If k is greater then size of string` `    ``// then return -1` `    ``if` `(k >= n)` `        ``return` `"-1"``;`   `    ``// a for storing 1` `    ``int` `a[n], i, j;`   `    ``// Mark all position with 1` `    ``for` `(i = 0; i < n; i++)` `        ``a[i] = 1;`   `    ``// Iterate string` `    ``for` `(i = 0; i < n;) {`   `        ``// Starting index` `        ``int` `start = i;`   `        ``// Position of start` `        ``int` `index = start;`   `        ``// Ending index` `        ``int` `end = min(start + k, n - 1);`   `        ``// Initialize min as start` `        ``char` `minn = str[start];`   `        ``// Iterate from start to end` `        ``for` `(j = start + 1; j <= end; j++) {`   `            ``// Checking for min and storing` `            ``// value and index of min` `            ``if` `(str[j] < minn) {` `                ``minn = str[j];` `                ``index = j;` `            ``}` `        ``}`   `        ``// Mark all max 0 before min` `        ``for` `(j = index - 1; j >= start and k != 0; j--) {` `            ``a[j] = 0;` `            ``k--;` `        ``}`   `        ``// Change i to next of last index` `        ``i = index + 1;` `    ``}`   `    ``// If k is not zero do the` `    ``// same as before` `    ``if` `(k) {` `        ``for` `(i = n - 1; i >= 0 and k != 0; i--) {` `            ``if` `(a[i]) {` `                ``a[i] = 0;` `                ``k--;` `            ``}` `        ``}` `    ``}`   `    ``// res for storing resulting string` `    ``string res = ``""``;`   `    ``// Storing resulting string` `    ``for` `(i = 0; i < n; i++) {` `        ``if` `(a[i]) {` `            ``res += str[i];` `        ``}` `    ``}`   `    ``// Return string` `    ``return` `res;` `}`   `// Driver code` `int` `main()` `{` `    ``string S = ``"fooland"``;` `    ``int` `K = 2;`   `    ``// Function Call` `    ``cout << lexicographicallySmallest(S, K) << endl;`   `    ``return` `0;` `}`

Java

 `// Java implementation`   `import` `java.io.*;`   `class` `GFG {`   `    ``// Function to find the setbit count` `    ``static` `public` `int` `countSetBits(``int` `n)` `    ``{` `        ``int` `count = ``0``;` `        ``while` `(n > ``0``) {` `            ``count += n & ``1``;` `            ``n >>= ``1``;` `        ``}` `        ``return` `count;` `    ``}`   `    ``// Function to find the lexicographically` `    ``// smallest possible string` `    ``static` `public` `String` `    ``lexicographicallySmallest(String str, ``int` `k)` `    ``{` `        ``int` `n = str.length();`   `        ``// If length is power of 2` `        ``// then divide k by 2` `        ``if` `(countSetBits(n) == ``1``)` `            ``k /= ``2``;`   `        ``// Else multiply k with 2` `        ``else` `            ``k *= ``2``;`   `        ``// If k is greater then size of string` `        ``// then return -1` `        ``if` `(k >= n)` `            ``return` `"-1"``;`   `        ``// a for storing 1` `        ``int``[] a = ``new` `int``[n];` `        ``int` `i, j;`   `        ``// Mark all position with 1` `        ``for` `(i = ``0``; i < n; i++)` `            ``a[i] = ``1``;`   `        ``// Iterate string` `        ``for` `(i = ``0``; i < n;) {`   `            ``// Starting index` `            ``int` `start = i;`   `            ``// Position of start` `            ``int` `index = start;`   `            ``// Ending index` `            ``int` `end = Math.min(start + k, n - ``1``);`   `            ``// Initialize min as start` `            ``char` `minn = str.charAt(start);`   `            ``// Iterate from start to end` `            ``for` `(j = start + ``1``; j <= end; j++) {`   `                ``// Checking for min and storing` `                ``// value and index of min` `                ``if` `(str.charAt(j) < minn) {` `                    ``minn = str.charAt(j);` `                    ``index = j;` `                ``}` `            ``}`   `            ``// Mark all max 0 before min` `            ``for` `(j = index - ``1``; j >= start && k != ``0``; j--) {` `                ``a[j] = ``0``;` `                ``k--;` `            ``}`   `            ``// Change i to next of last index` `            ``i = index + ``1``;` `        ``}`   `        ``// If k is not zero do the` `        ``// same as before` `        ``if` `(k != ``0``) {` `            ``for` `(i = n - ``1``; i >= ``0` `&& k != ``0``; i--) {` `                ``if` `(a[i] != ``0``) {` `                    ``a[i] = ``0``;` `                    ``k--;` `                ``}` `            ``}` `        ``}`   `        ``// res for storing resulting string` `        ``String res = ``""``;`   `        ``// Storing resulting string` `        ``for` `(i = ``0``; i < n; i++) {` `            ``if` `(a[i] != ``0``) {` `                ``res += str.charAt(i);` `            ``}` `        ``}`   `        ``// Return string` `        ``return` `res;` `    ``}`   `    ``public` `static` `void` `main(String[] args)` `    ``{` `        ``String S = ``"fooland"``;` `        ``int` `K = ``2``;`   `        ``// Function Call` `        ``System.out.println(lexicographicallySmallest(S, K));` `    ``}` `}`   `// This code is contributed by lokesh.`

Python

 `# Function to find the setbit count` `def` `countSetBits(n):` `    ``count ``=` `0` `    ``while` `n:` `        ``count ``+``=` `n & ``1` `        ``n >>``=` `1` `    ``return` `count`   `# Function to find the lexicographically` `# smallest possible string` `def` `lexicographicallySmallest(``str``, k):` `    ``n ``=` `len``(``str``)`   `    ``# If length is power of 2` `    ``# then divide k by 2` `    ``if` `countSetBits(n) ``=``=` `1``:` `        ``k ``/``/``=` `2` `    ``# Else multiply k with 2` `    ``else``:` `        ``k ``*``=` `2`   `    ``# If k is greater then size of string` `    ``# then return -1` `    ``if` `k >``=` `n:` `        ``return` `"-1"`   `    ``# a for storing 1` `    ``a ``=` `[``1``] ``*` `n`   `    ``# Iterate string` `    ``i ``=` `0` `    ``while` `i < n:`   `        ``# Starting index` `        ``start ``=` `i`   `        ``# Position of start` `        ``index ``=` `start`   `        ``# Ending index` `        ``end ``=` `min``(start ``+` `k, n ``-` `1``)`   `        ``# Initialize min as start` `        ``minn ``=` `str``[start]`   `        ``# Iterate from start to end` `        ``for` `j ``in` `range``(start ``+` `1``, end ``+` `1``):`   `            ``# Checking for min and storing` `            ``# value and index of min` `            ``if` `str``[j] < minn:` `                ``minn ``=` `str``[j]` `                ``index ``=` `j`   `        ``# Mark all max 0 before min` `        ``for` `j ``in` `range``(index ``-` `1``, start ``-` `1``, ``-``1``):` `            ``if` `k !``=` `0``:` `                ``a[j] ``=` `0` `                ``k ``-``=` `1`   `        ``# Change i to next of last index` `        ``i ``=` `index ``+` `1`   `    ``# If k is not zero do the` `    ``# same as before` `    ``if` `k:` `        ``for` `i ``in` `range``(n ``-` `1``, ``-``1``, ``-``1``):` `            ``if` `a[i]:` `                ``a[i] ``=` `0` `                ``k ``-``=` `1`   `    ``# res for storing resulting string` `    ``res ``=` `""`   `    ``# Storing resulting string` `    ``for` `i ``in` `range``(n):` `        ``if` `a[i]:` `            ``res ``+``=` `str``[i]`   `    ``# Return string` `    ``return` `res`   `# Driver code` `if` `__name__ ``=``=` `'__main__'``:` `    ``S ``=` `"fooland"` `    ``K ``=` `2`   `    ``# Function Call` `    ``print``(lexicographicallySmallest(S, K))`   `    ``# This code is contributed by aadityamaharshi21.`

C#

 `// C# implementation` `using` `System;`   `public` `class` `GFG {`   `  ``// Function to find the setbit count` `  ``static` `public` `int` `countSetBits(``int` `n)` `  ``{` `    ``int` `count = 0;` `    ``while` `(n > 0) {` `      ``count += n & 1;` `      ``n >>= 1;` `    ``}` `    ``return` `count;` `  ``}`   `  ``// Function to find the lexicographically` `  ``// smallest possible string` `  ``static` `public` `string` `    ``lexicographicallySmallest(``string` `str, ``int` `k)` `  ``{` `    ``int` `n = str.Length;`   `    ``// If length is power of 2` `    ``// then divide k by 2` `    ``if` `(countSetBits(n) == 1)` `      ``k /= 2;`   `    ``// Else multiply k with 2` `    ``else` `      ``k *= 2;`   `    ``// If k is greater then size of string` `    ``// then return -1` `    ``if` `(k >= n)` `      ``return` `"-1"``;`   `    ``// a for storing 1` `    ``int``[] a = ``new` `int``[n];` `    ``int` `i, j;`   `    ``// Mark all position with 1` `    ``for` `(i = 0; i < n; i++)` `      ``a[i] = 1;`   `    ``// Iterate string` `    ``for` `(i = 0; i < n;) {`   `      ``// Starting index` `      ``int` `start = i;`   `      ``// Position of start` `      ``int` `index = start;`   `      ``// Ending index` `      ``int` `end = Math.Min(start + k, n - 1);`   `      ``// Initialize min as start` `      ``char` `minn = str[start];`   `      ``// Iterate from start to end` `      ``for` `(j = start + 1; j <= end; j++) {`   `        ``// Checking for min and storing` `        ``// value and index of min` `        ``if` `(str[j] < minn) {` `          ``minn = str[j];` `          ``index = j;` `        ``}` `      ``}`   `      ``// Mark all max 0 before min` `      ``for` `(j = index - 1; j >= start && k != 0; j--) {` `        ``a[j] = 0;` `        ``k--;` `      ``}`   `      ``// Change i to next of last index` `      ``i = index + 1;` `    ``}`   `    ``// If k is not zero do the` `    ``// same as before` `    ``if` `(k != 0) {` `      ``for` `(i = n - 1; i >= 0 && k != 0; i--) {` `        ``if` `(a[i] != 0) {` `          ``a[i] = 0;` `          ``k--;` `        ``}` `      ``}` `    ``}`   `    ``// res for storing resulting string` `    ``string` `res = ``""``;`   `    ``// Storing resulting string` `    ``for` `(i = 0; i < n; i++) {` `      ``if` `(a[i] != 0) {` `        ``res += str[i];` `      ``}` `    ``}`   `    ``// Return string` `    ``return` `res;` `  ``}`   `  ``static` `public` `void` `Main()` `  ``{` `    ``string` `S = ``"fooland"``;` `    ``int` `K = 2;`   `    ``// Function Call` `    ``Console.WriteLine(lexicographicallySmallest(S, K));`   `  ``}` `}`   `// This code is contributed by ksam24000`

Javascript

 `// JavaScript code to implement the approach`   `        ``// Function to find the setbit count` `        ``const countSetBits = (n) => {` `            ``let count = 0;` `            ``while` `(n) {` `                ``count += n & 1;` `                ``n >>= 1;` `            ``}` `            ``return` `count;` `        ``}`   `        ``// Function to find the lexicographically` `        ``// smallest possible string` `        ``const lexicographicallySmallest = (str, k) => {` `            ``let n = str.length;`   `            ``// If length is power of 2` `            ``// then divide k by 2` `            ``if` `(countSetBits(n) == 1)` `                ``k = parseInt(k / 2);`   `            ``// Else multiply k with 2` `            ``else` `                ``k *= 2;`   `            ``// If k is greater then size of string` `            ``// then return -1` `            ``if` `(k >= n)` `                ``return` `"-1"``;`   `            ``// a for storing 1` `            ``let a = ``new` `Array(n).fill(0), i, j;`   `            ``// Mark all position with 1` `            ``for` `(i = 0; i < n; i++)` `                ``a[i] = 1;`   `            ``// Iterate string` `            ``for` `(i = 0; i < n;) {`   `                ``// Starting index` `                ``let start = i;`   `                ``// Position of start` `                ``let index = start;`   `                ``// Ending index` `                ``let end = Math.min(start + k, n - 1);`   `                ``// Initialize min as start` `                ``let minn = str[start];`   `                ``// Iterate from start to end` `                ``for` `(j = start + 1; j <= end; j++) {`   `                    ``// Checking for min and storing` `                    ``// value and index of min` `                    ``if` `(str[j] < minn) {` `                        ``minn = str[j];` `                        ``index = j;` `                    ``}` `                ``}`   `                ``// Mark all max 0 before min` `                ``for` `(j = index - 1; j >= start && k != 0; j--) {` `                    ``a[j] = 0;` `                    ``k--;` `                ``}`   `                ``// Change i to next of last index` `                ``i = index + 1;` `            ``}`   `            ``// If k is not zero do the` `            ``// same as before` `            ``if` `(k) {` `                ``for` `(i = n - 1; i >= 0 && k != 0; i--) {` `                    ``if` `(a[i]) {` `                        ``a[i] = 0;` `                        ``k--;` `                    ``}` `                ``}` `            ``}`   `            ``// res for storing resulting string` `            ``let res = ``""``;`   `            ``// Storing resulting string` `            ``for` `(i = 0; i < n; i++) {` `                ``if` `(a[i]) {` `                    ``res += str[i];` `                ``}` `            ``}`   `            ``// Return string` `            ``return` `res;` `        ``}`   `        ``// Driver code`   `        ``let S = ``"fooland"``;` `        ``let K = 2;`   `        ``// Function Call` `        ``console.log(lexicographicallySmallest(S, K));`   `        ``// This code is contributed by rakeshsahni`

Output

`and`

Time Complexity: O(N*N), As here we run a nested loop.
Auxiliary Space: O(N), using one array for marking all removed characters.

Optimized Approach: To solve the problem follow the below idea:

The idea is to use stack and maintain at least (n – K) non – decreasing characters starting with the smallest character we found.

Follow the steps to solve this problem:

• First correct the value of K by checking the length of the string is in the power of 2 or not.
• To check the length of the string is present in the power of 2 or not we can use the Bitwise-and operator.
• If Bitwise-and of string_length and (string_length – 1) gives 0 that means string_length has only one bit which means it is in the power of 2.
• If the size of the string is in the power of 2 then divide K by 2 else multiply K by 2.
• Now check if K is greater than or equal to the size of the string then return -1.
• Else, create a stack for storing the characters in non-decreasing order.
• Run a loop and check for every character:
• If the top element of the stack is greater than the char that means we have to consider the string from here because we found here lowest character so we have to remove the char from the stack and decrease K by one till the stack is empty or the stack top element is less than the char and K is greater than zero (because we have to remove only K characters).
• Push the char into the stack
• Check if the number of removed chars is less than K then remove that number of chars from the stack.
• Copy all stack characters into a variable string ans and reverse the ans(because we copied from the stack).
• Return the Ans.

Below is the implementation of the above approach.

C++

 `// C++ code to implement the approach`   `#include ` `using` `namespace` `std;`   `// Function to find the lexicographically` `// smallest string` `string lexicographicallySmallest(string S, ``int` `k)` `{` `    ``string ans = ``""``;` `    ``int` `l = S.length();`   `    ``if` `(l & (l - 1))` `        ``k += k;` `    ``else` `        ``k /= 2;`   `    ``if` `(k >= l)` `        ``return` `"-1"``;`   `    ``stack<``char``> st;` `    ``for` `(``int` `i = 0; i < l; i++) {` `        ``while` `(!st.empty() && k > 0 && st.top() > S[i]) {` `            ``st.pop();` `            ``k--;` `        ``}` `        ``st.push(S[i]);` `    ``}`   `    ``if` `(k > 0)` `        ``while` `(k--)` `            ``st.pop();`   `    ``while` `(!st.empty()) {` `        ``ans = st.top() + ans;` `        ``st.pop();` `    ``}` `    ``return` `ans;` `}`   `// Driver Code` `int` `main()` `{` `    ``string S = ``"fooland"``;` `    ``int` `K = 2;`   `    ``// Function Call` `    ``cout << lexicographicallySmallest(S, K);`   `    ``return` `0;` `}`

Java

 `// Java code to implement the approach` `import` `java.util.*;`   `public` `class` `GFG {`   `    ``// Function to find the lexicographically` `    ``// smallest string` `    ``public` `static` `String lexicographicallySmallest(String S,` `                                                   ``int` `k)` `    ``{` `        ``String ans = ``""``;` `        ``int` `l = S.length();`   `        ``if` `((l & (l - ``1``)) != ``0``)` `            ``k += k;` `        ``else` `            ``k /= ``2``;`   `        ``if` `(k >= l)` `            ``return` `"-1"``;`   `        ``Stack st = ``new` `Stack();` `        ``for` `(``int` `i = ``0``; i < l; i++) {` `            ``while` `(!st.empty() && k > ``0` `                   ``&& st.peek() > S.charAt(i)) {` `                ``st.pop();` `                ``k--;` `            ``}` `            ``st.push(S.charAt(i));` `        ``}`   `        ``if` `(k > ``0``)` `            ``while` `(k > ``0``)` `                ``st.pop();` `        ``k--;`   `        ``while` `(!st.empty()) {` `            ``ans = st.peek() + ans;` `            ``st.pop();` `        ``}` `        ``return` `ans;` `    ``}`   `    ``// Driver Code` `    ``public` `static` `void` `main(String args[])` `    ``{` `        ``String S = ``"fooland"``;` `        ``int` `K = ``2``;`   `        ``// Function Call` `        ``System.out.println(lexicographicallySmallest(S, K));` `    ``}` `}`   `// This code is contributed by Samim Hossain Mondal.`

Python3

 `# Python code to implement the approach`   `# Function to find the lexicographically` `# smallest string` `def` `lexicographicallySmallest(S, k):` `    ``ans``=``""` `    ``l ``=` `len``(S)` `    `  `    ``if``(l&(l ``-` `1``)):` `        ``k ``+``=` `k` `    ``else``:` `        ``k ``/``=` `2` `    `  `    ``if``(k >``=` `l):` `        ``return` `"-1"` `    `  `    ``st ``=` `[]` `    ``for` `i ``in` `range``(l):` `        ``while``(``len``(st) ``and` `k > ``0` `and` `st[``len``(st) ``-` `1``] > S[i]):` `            ``st.pop()` `            ``k ``=` `k ``-` `1` `        ``st.append(S[i])` `        `  `    ``if``(k > ``0``):` `        ``while``(k > ``0``):` `            ``k ``=` `k ``-` `1` `            ``st.pop()` `    `  `    ``while``(``len``(st)):` `        ``ans ``=` `st[``len``(st) ``-` `1``] ``+` `ans` `        ``st.pop()` `        `  `    ``return` `ans` `    `  `# Driver Code` `S ``=` `"fooland"` `K ``=` `2`   `# Function Call` `print``(lexicographicallySmallest(S,K))`   `# This code is contributed by Pushpesh Raj.`

C#

 `// C# code to implement the approach`   `using` `System;` `using` `System.Collections;` `using` `System.Collections.Generic;`   `public` `class` `GFG {`   `    ``// Function to find the lexicographically` `    ``// smallest string` `    ``public` `static` `string` `lexicographicallySmallest(``string` `S,` `                                                   ``int` `k)` `    ``{` `        ``string` `ans = ``""``;` `        ``int` `l = S.Length;`   `        ``if` `((l & (l - 1)) != 0)` `            ``k += k;` `        ``else` `            ``k /= 2;`   `        ``if` `(k >= l)` `            ``return` `"-1"``;`   `        ``Stack st = ``new` `Stack();` `        ``for` `(``int` `i = 0; i < l; i++) {` `            ``while` `(st.Count != 0 && k > 0` `                   ``&& (``char``)st.Peek() > S[i]) {` `                ``st.Pop();` `                ``k--;` `            ``}` `            ``st.Push(S[i]);` `        ``}`   `        ``if` `(k > 0)` `            ``while` `(k > 0)` `                ``st.Pop();` `        ``k--;`   `        ``while` `(st.Count != 0) {` `            ``ans = st.Peek() + ans;` `            ``st.Pop();` `        ``}` `        ``return` `ans;` `    ``}`   `    ``static` `public` `void` `Main()` `    ``{`   `        ``// Code` `        ``string` `S = ``"fooland"``;` `        ``int` `K = 2;`   `        ``// Function call` `        ``Console.WriteLine(lexicographicallySmallest(S, K));` `    ``}` `}`   `// This code is contributed by lokeshmvs21.`

Javascript

 `// Javascript code to implement the approach`   `// Function to find the lexicographically` `// smallest string` `function` `lexicographicallySmallest( S, k)` `{` `    ``let ans = ``""``;` `    ``let l = S.length;`   `    ``if` `(l & (l - 1) !=0)` `        ``k += k;` `    ``else` `        ``k /= 2;`   `    ``if` `(k >= l)` `        ``return` `"-1"``;`   `    ``let st=[];` `    ``for` `(let i = 0; i < l; i++) {` `        ``while` `( st.length!=0 && k > 0 && st[st.length-1] > S[i]) {` `            ``st.pop();` `            ``k--;` `        ``}` `        ``st.push(S[i]);` `    ``}`   `    ``if` `(k > 0)` `        ``while` `(k--)` `            ``st.pop();`   `    ``while` `(st.length!=0) {` `        ``ans = st[st.length-1] + ans;` `        ``st.pop();` `    ``}` `    ``return` `ans;` `}`   `// Driver Code`   `    ``let S = ``"fooland"``;` `    ``let K = 2;`   `    ``// Function Call` `   ``console.log(lexicographicallySmallest(S, K));`   `  ``// This code is contributed by garg28harsh.`

Output

`and`

Time Complexity: O(N + K), for traversal of every element of the string and inside the loop we traverse at most K times for the removal of strings from the stack so overall time is O(N + K).
Auxiliary Space: O(N), For storing characters in the stack.

My Personal Notes arrow_drop_up
Related Articles