【数据结构-栈】【位运算优化】力扣3170. 删除星号以后字典序最小的字符串

给你一个字符串 s 。它可能包含任意数量的 '' 字符。你的任务是删除所有的 '' 字符。

当字符串还存在至少一个 '*' 字符时,你可以执行以下操作:

删除最左边的 '' 字符,同时删除该星号字符左边一个字典序 最小 的字符。如果有多个字典序最小的字符,你可以删除它们中的任意一个。
请你返回删除所有 '
' 字符以后,剩余字符连接而成的

字典序最小

的字符串。

示例 1:

输入:s = "aaba*"

输出:"aab"

解释:

删除 '*' 号和它左边的其中一个 'a' 字符。如果我们选择删除 s3 ,s 字典序最小。

示例 2:

输入:s = "abc"

输出:"abc"

解释:

字符串中没有 '*' 字符。

法一

cpp 复制代码
class Solution {
public:
    string clearStars(string s) {
        int n = s.size();
        stack<int> st[26];
        for(int i = 0; i < n; i++){
            if(s[i] != '*'){
                st[s[i] - 'a'].push(i);
            }
            else{
                for(auto &p : st){
                    if(!p.empty()){
                        s[p.top()] = '*';
                        p.pop();
                        break;
                    }
                }
            }
        }
        s.erase(remove(s.begin(),s.end(),'*'), s.end());
        return s;
    }
};

时间复杂度 :O(n∣Σ∣),其中 n 是 s 的长度,∣Σ∣ 为字符集合的大小,本题字符均为小写字母,所以 ∣Σ∣=26。
空间复杂度:O(n+∣Σ∣)。

这道题我们首先建立一个大小为26的栈数组,每个sti代表一个栈。我们按顺序遍历字符串,在遍历过程中,如果字符不为*,那么就在栈数组对应的栈推入这个字符的位置。比如说字符为a在i=0的位置,那么就是st0 = {0}。

如果字符是*,那么我们就循环栈数组,栈数组会按字典序从小到大进行查询,优先删除字典序最小的字符。我们查找到字典序最小的字符所处的栈后,栈顶的元素代表这当前最靠右的字符的位置,我们在字符串s中将这个字符 s[p.top()] = '*';设为星号,代表这个字符已经被删除。然后执行完后,该栈就要弹出栈顶的元素的位置,因为他已经被删除不存在。一旦找到一个不为空的栈,就break,停止遍历栈数组。

最后 s.erase(remove(s.begin(), s.end(), '*'), s.end());,举个例子:

remove 会将字符串变为 "abcdef**",并返回一个指向第一个 '' 的位置的迭代器。
erase 会删除这两个 '
',最终 s 变为 "abcdef"。

位运算优化

cpp 复制代码
class Solution {
public:
    string clearStars(string s) {
        int n = s.size(), mask = 0;
        stack<int> st[26];
        for(int i = 0; i < n; i++){
            if(s[i] != '*'){
                st[s[i] - 'a'].push(i);
                mask |= 1<<(s[i]-'a');
            }
            else{
                int k = __builtin_ctz(mask);
                auto& p = st[k];
                s[p.top()] = '*';
                p.pop();
                if(p.empty()){
                    mask ^= 1 << k;
                }
            }
        }
        s.erase(remove(s.begin(),s.end(),'*'), s.end());
        return s;
    }
};

时间复杂度 :O(n+∣Σ∣),其中 n 是 s 的长度,∣Σ∣ 为字符集合的大小,本题字符均为小写字母,所以 ∣Σ∣=26。
空间复杂度:O(n+∣Σ∣)。

位运算优化的地方在我们之前通过遍历栈数组来查找最小字典序的栈是哪个,我们可以使用一个二进制数mask通过0和1来记录每个栈是否不为空。在循环字符串s的过程中,字符不为星号,则让mask对应位置变为1,说明这个字母存在。

如果遍历s的过程中字符为星号,则定义一个整数k,调用内置函数__builtin_ctz(mask)来返回mask中最右侧的1的右边有多少个0。k就是我们需要查找的栈数组中的栈的位置。然后最后,如果栈推出元素后为空,那么就通过异或1来将mask中的1置为0,代表这个栈为空。

相关推荐
指掀涛澜天下惊4 分钟前
强化学习进阶篇八 策略梯度算法
深度学习·学习·算法·强化学习
乌萨奇也要立志学C++9 分钟前
【洛谷】kmp算法
开发语言·算法
禹凕17 分钟前
Dijkstra算法详解与应用
python·算法
YaraMemo1 小时前
元启发式算法框架
人工智能·算法·5g·信息与通信·启发式算法·信号处理
weixin_307779131 小时前
一维无粘 Burgers 方程的激波形成问题:MacCormack 格式求解
c++·算法·matlab
HugoStudio_SWAN2 小时前
洛谷 B4500 / B4449 / B3843 凯撒密码、密码强度与密码合规——加密与安全的三道门
c++·学习·程序人生·算法·安全
枫叶林FYL3 小时前
【群体智能集群控制工程实践】第3章 一致性协同算法
算法
禹凕3 小时前
滑动窗口算法实战指南
python·算法
DisonTangor3 小时前
【腾讯混元雪耻归来】 Hy4 preview:770B 参数 MoE 旗舰模型,1M 上下文全面开源
人工智能·算法·开源·aigc·腾讯云·腾讯云ai代码助手
明月_清风4 小时前
从二叉树到 B+ 树:一文搞懂工程中「树」的演化之道
数据结构·算法·go