查看原文
其他

526,删除字符串中的所有相邻重复项

博哥 数据结构和算法 2022-05-19

It may not be pretty, but we headed to the city. 

其貌虽不扬,扬帆亦远航。

问题描述



给出由小写字母组成的字符串S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。


在S上反复执行重复项删除操作,直到无法继续删除。


在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。


示例:

输入:"abbaca"

输出:"ca"

解释

例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。


提示:

  • 1 <= S.length <= 20000

  • S 仅由小写英文字母组成。


使用栈解决



这题让把挨着的并且相同的字符同时给删除,最简单的实现方式就是使用栈来解决。


我们遍历字符串中的所有字母:

1,如果栈为空

  • 就把当前字母加入到栈中。


2,如果栈不为空

  • 如果当前字母等于栈顶元素,说明他俩是相邻且相同的,让他俩同时消失。

  • 如果当前字母不等于栈顶元素,说明他俩是相邻但不相同,直接让当前字母入栈。


具体以示例为例来看下视频

上面视频中是先入栈之后,如果两个有相同的在同时消失,其实我们不需要先入栈,而是先比较,如果相同让栈顶元素出栈即可,来看下代码

1public String removeDuplicates(String S) {
2    char[] chars = S.toCharArray();
3    Stack<Character> stack = new Stack<>();
4    int index = 0;
5    int length = S.length();
6    while (index < length) {
7        char current = chars[index++];
8        if (!stack.empty() && stack.peek() == current) {
9            //如果栈顶的值和当前遍历的值相同,他两直接消失
10            stack.pop();
11        } else {
12            //如果栈为空,或者栈顶元素和当前值不相同,就把当前值压入栈
13            stack.push(current);
14        }
15    }
16    //下面是把栈中的元素转化为字符串
17    StringBuilder stringBuilder = new StringBuilder(stack.size());
18    while (!stack.empty())
19        stringBuilder.append(stack.pop());
20    return stringBuilder.reverse().toString();
21}


使用双指针解决



大家应该都玩过连连看吧,就是挨着的多个相同的会同时消失。我们这里类似于连连看,挨着两个相同的同时消失,可以使用两个指针。


  • 一个right一直往右移动,然后把指向的值递给left指向的值即可。

  • 一个left每次都会比较挨着的两个是否相同,如果相同,他两同时消失。


具体看下视频

代码如下

1public String removeDuplicates(String S) {
2    int left = 0;
3    int right = 0;
4    int length = S.length();
5    char[] chars = S.toCharArray();
6    while (right < length) {
7        //先把右边的字符赋值给左边
8        chars[left] = chars[right];
9        //然后判断左边挨着的两个字符是否相同,如果相同,
10        //他两同时消失,也就是left往回退两步
11        if (left > 0 && chars[left - 1] == chars[left])
12            left -= 2;
13        ++right;
14        ++left;
15    }
16    return new String(chars, 0, left);
17}

还可以使用StringBuilder,原理都是一样的,来看下代码

1public String removeDuplicates(String S) {
2    StringBuilder stringBuilder = new StringBuilder();
3    char[] chars = S.toCharArray();
4    for (char ch : chars) {
5        int size = stringBuilder.length();
6        if (size > 0 && stringBuilder.charAt(size - 1) == ch) {
7            stringBuilder.deleteCharAt(size - 1);
8        } else {
9            stringBuilder.append(ch);
10        }
11    }
12    return stringBuilder.toString();
13}


总结



这题使用栈是最容易想到的,每次只需要比较要入栈的值和栈顶元素即可,如果一样,就同时消失。当然还可以使用双端队列,他是两头都可以添加和删除的一种数据结构,具体可以看下359,数据结构-3,队列


508,使用栈来判断有效的括号

500,验证栈序列

497,双指针验证回文串

398,双指针求无重复字符的最长子串


截止到目前我已经写了500多道算法题了,为了方便大家阅读,我把部分算法题整理成了pdf文档,目前有800多页,大家可以在公众号中回复关键字“pdf”即可获取下载链接。


你点的每个赞,我都认真当成了喜欢

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存