Hey, tech explorers! ๐ Today, letโs decode a delightful greedy string manipulation problem โ LeetCode 3170: Lexicographically Minimum String After Removing Stars. We'll walk through a structured approach and implement it step by step in C++, JavaScript, and Python. Letโs go! ๐
๐ Problem Overview
Youโre given a string s
containing lowercase letters and asterisks *
.
You must repeatedly perform this operation until no *
is left:
- Remove the leftmost
*
. - Remove the smallest non-
*
character to its left. If there are multiple smallest characters, you can choose any.
๐ Goal: Return the lexicographically smallest string after all *
and their associated characters have been deleted.
๐ง Intuition & Strategy
This problem is all about greedy decision-making. At every step, you must:
- Process characters left to right.
- For every
*
, find the smallest character to its left and remove it. - Make sure you handle characters efficiently โ especially for large strings (
1 <= s.length <= 10โต
).
We use:
- A min-heap to track the smallest character encountered so far.
- An index tracker for each character (
a
toz
) to know their positions in the string. - A marking technique (using
!
) to flag removed characters. - A final pass to build the answer string.
โ๏ธ C++ Code (Efficient & Clean)
class Solution {
public:
string clearStars(string s) {
priority_queue<char, vector<char>, greater<char>> pq;
vector<vector<int>> indices(26);
for (int i = 0; i < s.size(); i++) {
if (s[i] == '*') {
char ch = pq.top();
s[indices[ch - 'a'].back()] = '!'; // mark as deleted
indices[ch - 'a'].pop_back();
if (indices[ch - 'a'].empty()) {
pq.pop(); // remove from heap if no more left
}
} else {
if (indices[s[i] - 'a'].empty()) {
pq.push(s[i]); // new character, push into heap
}
indices[s[i] - 'a'].push_back(i);
}
}
string res = "";
for (char c : s) {
if (c >= 'a') res += c;
}
return res;
}
};
๐ JavaScript Version
var clearStars = function(s) {
const indices = Array.from({ length: 26 }, () => []);
const arr = s.split('');
const pq = [];
const pushHeap = (ch) => {
if (!pq.includes(ch)) {
pq.push(ch);
pq.sort(); // simple sort-based heap
}
};
for (let i = 0; i < arr.length; i++) {
if (arr[i] === '*') {
while (pq.length && indices[pq[0].charCodeAt(0) - 97].length === 0) {
pq.shift(); // clean up dead entries
}
const smallest = pq[0];
const idx = indices[smallest.charCodeAt(0) - 97].pop();
arr[idx] = '!';
if (indices[smallest.charCodeAt(0) - 97].length === 0) {
pq.shift();
}
} else {
const code = arr[i].charCodeAt(0) - 97;
if (indices[code].length === 0) pushHeap(arr[i]);
indices[code].push(i);
}
}
return arr.filter(c => c >= 'a').join('');
};
๐ Python Version
import heapq
from collections import defaultdict
class Solution:
def clearStars(self, s: str) -> str:
s = list(s)
pq = []
indices = defaultdict(list)
for i, ch in enumerate(s):
if ch == '*':
while pq and not indices[pq[0]]:
heapq.heappop(pq)
smallest = pq[0]
idx = indices[smallest].pop()
s[idx] = '!' # mark as deleted
if not indices[smallest]:
heapq.heappop(pq)
else:
if not indices[ch]:
heapq.heappush(pq, ch)
indices[ch].append(i)
return ''.join(c for c in s if c >= 'a')
๐งช Test Cases
Input: "aaba*"
Output: "aab"
Explanation: Remove the last 'a' before the '*' for smallest result.
Input: "abc"
Output: "abc"
Explanation: No stars, nothing to remove.
Input: "zz*yy*aa*"
Output: "zya"
Explanation: Always remove the smallest character before each '*'.
Input: "aaab*bbc*"
Output: "aabb"
๐งฎ Time & Space Complexity
Time Complexity: O(n log k) where k โค 26 // Heap operations over 26 letters
Space Complexity: O(n) // Position tracking and character marking
โจ Wrap Up
This problem is a wonderful exercise in greedy thinking and priority queues. ๐ก
By carefully tracking the smallest deletable characters and handling each star in order, weโre able to produce the lexicographically smallest result.
If you found this helpful, drop a โค๏ธ, leave a comment, or follow for more clean walkthroughs!
Happy coding, explorers! ๐๐ป
Top comments (2)
Great Explanation, was stuck on this problem for hours
Understandable, took me a while to figure it out myself.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.