【数据结构-栈】【位运算优化】力扣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,代表这个栈为空。

相关推荐
闻缺陷则喜何志丹7 分钟前
详细设计说明书的内容要求
算法·测试·存储
Logic10112 分钟前
C语言/数据结构位运算题解:异或XOR找出糖葫芦派对中的“独一无二山楂果数量“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
和裕13 分钟前
定制纸箱刀卡、平卡、隔档分别是什么?结构与适用场景区别全解析
大数据·运维·网络·人工智能·算法
Tisfy36 分钟前
LeetCode 3723.数位平方和的最大值:构造
数学·算法·leetcode·字符串·题解
hetao173383741 分钟前
联盟场-提高组-R4 & ZYZSC-S-Round 7
c++·算法
碧海银沙音频科技研究院1 小时前
基于炬芯ATS3089X音箱的音乐播放歌词显示功能实现
人工智能·驱动开发·嵌入式硬件·算法
知识分享小能手1 小时前
C学习教程,从入门到精通,C语言数组 —— 知识点详解(8)
c语言·学习·算法
hetao17338371 小时前
联盟场-提高组-R2 & ZYZSC-S-Round 5
c++·算法
其实防守也摸鱼1 小时前
Codex 下载与本地部署实战指南
linux·服务器·前端·数据库·算法·ai
南极企鹅1 小时前
生产环境gc文件分析
java·jvm·算法