leetcode【栈与队列—简单】 1047. 删除字符串中的所有相邻重复项

简介: leetcode【栈与队列—简单】 1047. 删除字符串中的所有相邻重复项

题目


题目来源leetcode


leetcode地址:1047. 删除字符串中的所有相邻重复项,难度:简单。


题目描述(摘自leetcode):


给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例:
输入:"abbaca"
输出:"ca"
解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。
提示:
1 <= S.length <= 20000
S 仅由小写英文字母组成。


本地调试代码:


class Solution {
    public String removeDuplicates(String s) {
        ...
    }
    public static void main(String[] args) {
        System.out.println(new Solution().removeDuplicates("abbaca"));
    }
}



题解


NO1:栈解决


思路:遍历字符时,每次先判断当前栈顶元素是否与要入栈的元素相同,如果相同出栈,不相同入栈。最后将栈中的字符进行一一拼接返回。


示例:"abbaca" stack=[]
① 字符'a',当前栈为空直接入栈  stack=['a']
② 字符'b',栈不为空,与栈顶元素a比较,不相同入栈  stack=['a','b']
③ 字符'b',栈不为空,与栈顶元素b比较,相同出栈  stack=['a']
④ 字符'a',栈不为空,与栈顶元素b比较,相同出栈  stack=[]
⑤ 字符'c',当前栈为空直接入栈  stack=['c']
⑥ 字符'a',栈不为空,与栈顶元素c比较,不相同入栈  stack=['a','c']
最终从前往往后将元素移出进行拼接,返回"ac"


代码:


class Solution {
    public String removeDuplicates(String s) {
        Deque<Character> stack = new LinkedList<>();
        for (char c : s.toCharArray()) {
            //当前栈不为空,且栈顶与当前字符相同出栈
            if(!stack.isEmpty() && stack.peek() == c){
                stack.pop();
            }else{//否则直接入栈
                stack.push(c);
            }
        }
        StringBuilder str = new StringBuilder();
        while(!stack.isEmpty()){
            str = str.append(stack.pollLast());
        }
        return str.toString();
    }
}



NO2:字符串作栈


思路:使用字符串作栈的好处就是可以省去上面提交中拼接的操作,最终留在字符串里的就是要返回出去的。


示例:"abbaca"  str="" top=-1
① 字符'a' 字符串(栈)为空,直接拼接 str="a"  top=0
② 字符'b' 字符串(栈)不为空,与栈顶不相同,直接拼接 str="ab" top=1
③ 字符'b' 字符串(栈)不为空,与栈顶相同,删除指定元素 str="a" top=0
④ 字符'a' 字符串(栈)不为空,与栈顶相同,删除指定元素 str="" top=-1
⑤ 字符'c' 字符串(栈)为空,直接拼接 str="c"  top=0
⑥ 字符'b' 字符串(栈)不为空,与栈顶不相同,直接拼接 str="ca" top=1
最终直接返回str="ca"

 


代码:


class Solution {
    //目的是拿到不重复的字符拼接内容
    public String removeDuplicates(String s) {
        //直接来拿字符串来作为栈进行操作,最终剩下来的就是不重复的
        StringBuilder str = new StringBuilder();
        int top = -1;
        for (char c : s.toCharArray()) {
            if(top >= 0 && c == str.charAt(top)){
                str.deleteCharAt(top--);
            }else{
                str.append(c);
                top++;
            }
        }
        return str.toString();
    }
}




NO3、双指针(原数组上操作)


思路:直接对原数组进行操作,不相邻的重复元素直接覆盖旧元素,最终直接截取原数组指定长度内容返回。


fast指针用来进行遍历一遍字符串的,[0,slow)永远表示的是非相邻重复项
示例:s="abbaca"  slow=0,fast=0
① 字符'a' s[0]=s[0] (s="abbaca") slow=1,fast=1  | [0,slow)=> "a"
② 字符'b' s[1]=s[1] (s="abbaca") slow=2,fast=2  | [0,slow)=> "ab"
③ 字符'b' s[2]=s[2] (s="abbaca")(s[2]==s[1] => b=b重复,slow-1) slow=1,fast=3    | [0,slow)=> "a"
④ 字符'a' s[1]=s[3] (s="aabaca")(s[1]==s[0] => a=a重复,slow-1) slow=0,fast=4    | [0,slow)=> ""
⑤ 字符'c' s[0]=s[4] (s="cabaca")(slow=0,slow+1) slow=1,fast=5     | [0,slow)=> "c"
⑥ 字符'a' s[1]=s[5] (s="cabaca")(s[1]!=s[0],slow++) slow=1,fast=4    | [0,slow)=> "ca"
最终直接返回"ca"即可


代码:


//快慢指针,时间复杂度O(n),空间复杂度O(1)
public String removeDuplicates(String s) {
    //定义双指针
    int slow = 0;//左指针的目的是①检测是否有相等,有后退,无前进。②实时更新当前最新位置值(方便下次进行对比以及旧值的覆盖,旧的值已无用)
    int fast = 0;//右指针负责的工作是进行遍历作用
    char[] chars = s.toCharArray();
    while(fast < s.length()){
        chars[slow] = chars[fast];
        if(slow > 0 && chars[slow]==chars[slow-1]){
            slow--;
        }else{
            slow++;
        }
        fast++;
    }
    //[0,slow)区间值
    return new String(chars,0,slow);
}


相关文章
|
Go 索引
【LeetCode 热题100】394:字符串解码(详细解析)(Go语言版)
本文详细解析了 LeetCode 热题 394:字符串解码。题目要求对编码字符串如 `k[encoded_string]` 进行解码,其中 `encoded_string` 需重复 `k` 次。文章提供了两种解法:使用栈模拟和递归 DFS,并附有 Go 语言实现代码。栈解法通过数字栈与字符串栈记录状态,适合迭代;递归解法则利用函数调用处理嵌套结构,代码更简洁。两者时间复杂度均为 O(n),但递归需注意栈深度问题。文章还总结了解题注意事项及适用场景,帮助读者更好地掌握字符串嵌套解析技巧。
407 6
|
存储 机器学习/深度学习 缓存
🚀 力扣热题 394:字符串解码(详细解析)(Go语言版)
文章提供了两种解法:栈结构和递归解法。栈解法通过维护数字栈与字符串栈,依次处理 `[` 和 `]`,构造解码结果;递归解法则利用函数调用逐层解析嵌套结构。两者时间复杂度均为 $O(n)$,空间复杂度也为 $O(n)$。栈解法直观易懂,适合初学者;递归解法优雅简洁,适合处理深度嵌套规则。掌握这两种方法,可灵活应对类似问题,提升解题能力。
523 11
|
C++
Leetcode第43题(字符串相乘)
本篇介绍了一种用C++实现的字符串表示的非负整数相乘的方法,通过逆向编号字符串,将乘法运算转化为二维数组的累加过程,最后处理进位并转换为字符串结果,解决了两个大数相乘的问题。
189 9
|
JavaScript
力扣3333.找到初始输入字符串Ⅱ
【10月更文挑战第9天】力扣3333.找到初始输入字符串Ⅱ
231 1
【LeetCode 24】225.用队列实现栈
【LeetCode 24】225.用队列实现栈
152 0
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
449 6
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
238 6
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
541 2
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
453 4
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
|
机器学习/深度学习 人工智能 自然语言处理
280页PDF,全方位评估OpenAI o1,Leetcode刷题准确率竟这么高
【10月更文挑战第24天】近年来,OpenAI的o1模型在大型语言模型(LLMs)中脱颖而出,展现出卓越的推理能力和知识整合能力。基于Transformer架构,o1模型采用了链式思维和强化学习等先进技术,显著提升了其在编程竞赛、医学影像报告生成、数学问题解决、自然语言推理和芯片设计等领域的表现。本文将全面评估o1模型的性能及其对AI研究和应用的潜在影响。
493 1