Introduction
In many string manipulation problems, we are asked to remove a certain number of characters while preserving the relative order of the remaining characters. The goal is often to produce the smallest possible string in lexicographical (dictionary) order.
This problem adds an interesting twist: before removing characters, we must first modify the value of k based on the length of the string.
Let's understand the problem, derive an optimal solution, and implement it efficiently in Java.
Problem Statement
Given:
A string
sconsisting of lowercase English letters.An integer
k.
Before removing characters, correct the value of k as follows:
If the length of the string is a power of 2, reduce
kby half.Otherwise, multiply
kby 2.
After correction, remove exactly k characters so that the resulting string is lexicographically smallest.
Return:
The smallest possible string.
-1if it is impossible to remove the required number of characters or the resulting string becomes empty.
Example 1
Input
s = "fooland"
k = 2
Length = 7
7 is not a power of 2.
Corrected k:
k = 2 × 2 = 4
Remove 4 characters optimally:
fooland
↓↓↓↓
and
Output
"and"
Example 2
Input
s = "code"
k = 4
Length = 4
4 is a power of 2.
Corrected k:
k = 4 / 2 = 2
After removing 2 characters:
code → cd
Output
"cd"
Understanding Lexicographical Order
Lexicographical order is the same as dictionary order.
Examples:
abc < acb
cat < dog
and < fool
To obtain the smallest string, smaller characters should appear as early as possible.
Key Observation
Suppose we have:
cbad
and need to remove one character.
Keeping c at the beginning is not optimal because b is smaller.
If we remove c:
bad
which is lexicographically smaller.
This suggests:
Whenever a larger character appears before a smaller character, we should remove the larger one if removals are still available.
This is exactly where a Monotonic Stack helps.
Monotonic Stack Approach
We maintain characters in increasing order.
For every new character:
Compare it with the stack top.
If the top character is greater than the current character and removals remain:
Remove the top character.
Continue until no more beneficial removals exist.
Push the current character.
This guarantees the smallest possible prefix at every step.
Step-by-Step Example
Input
s = "fooland"
k = 2
Length = 7
Corrected:
k = 4

Join the conversation! Your thoughts help the community grow.