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

于2021.11.17练习

题目链接

本题其实是一个“开心消消乐”的问题,下面展示了两种解法。

1.1 解法1:常规解法之栈

1.1.1 思路

思路:因为要删除的重复项是两个相邻且相同的字母,故每次都要比较当前元素和上一个元素,因此想到用栈。

首先遍历当前字符串,当遍历到某一个字符时,先判断该字符和栈顶元素是否相等,如果相等,就将栈顶元素弹出;如果不等或者此时堆栈为空,就将该字符入栈。

最后遍历完成后,将栈中的字符倒着输出。一开始我写的是res += stack.pop(),这种写法相当于res = res + stack.pop(),是将新弹出的元素添加在了后面,输出的结果为ca;而我们要的结果为ac,因此应该写成res = stack.pop() + res,这样保证新弹出的元素永远在最前面。

1.1.2 代码实现

执行用时:170 ms, 在所有 Java 提交中击败了5.18%的用户

内存消耗:40.7 MB, 在所有 Java 提交中击败了8.13%的用户

class Solution {
    public String removeDuplicates(String s) {
        Stack<Character> stack = new Stack<>();
        int n = s.length();
        for(int i = 0;i < n;i++){
            char cur = s.charAt(i);
            if(stack.empty() || cur != stack.peek()){
                stack.push(cur);
            }
            else{
                stack.pop();
            }
        }
        String res = "";
        while(!stack.empty()){
            res = stack.pop() + res;
        }
        return res;
    }
}

上面利用String的+运算进行添加,效率会很低,因此考虑用StringBuilder做改进。这里可以详细看下String和StringBuilder的区别!


执行用时:28 ms, 在所有 Java 提交中击败了34.59%的用户

内存消耗:39.1 MB, 在所有 Java 提交中击败了49.30%的用户

class Solution {
    public String removeDuplicates(String s) {
        Stack<Character> stack = new Stack<>();
        int n = s.length();
        for(int i = 0;i < n;i++){
            char cur = s.charAt(i);
            if(stack.empty() || cur != stack.peek()){
                stack.push(cur);
            }
            else{
                stack.pop();
            }
        }
        StringBuilder res = new StringBuilder();
        while(!stack.empty()){
            res.append(stack.pop());
        }
        return res.reverse().toString();
    }
}

1.1.3 方法小结

代码中用到的一些StringBuilder的方法,进行下面总结:

  1. 添加元素,使用append()

  2. 反转字符序列,使用reverse()

  3. 将StringBuilder转换为String,使用toString()

1.2 解法2:双指针原地法

1.2.1 思路

思路:将字符串转换为字符数组,用一个指针i去遍历原字符数组,用一个指针top指向结果数组的最后一个位置。当top为-1(说明结果数组此时为空)或者原字符数组中的元素不等于top指向的元素,就将top后移一位,并且将元素赋给top位置;否则的话,说明相邻元素是重复的,就将top前移一位。整个过程都是在原字符数组上进行的,并没有开辟新的数组,因此称为原地算法。

小结:个人感觉这种双指针原地的思想类似于leetcode26.删除有序数组中的重复项以及leetcode27.移除元素

1.2.2 代码实现

执行用时:3 ms, 在所有 Java 提交中击败了100.00%的用户

内存消耗:38.8 MB, 在所有 Java 提交中击败了87.94%的用户

class Solution {
    public String removeDuplicates(String s) {
        char[] ch = s.toCharArray();
        int top = -1;
        for(int i = 0;i < ch.length;i++){
            if(top == -1 || ch[i] != ch[top]){
                ch[++top] = ch[i];
            }
            else{
                top--;
            }
        }
        return String.valueOf(ch,0,top + 1);
    }
}

1.2.3 方法总结

代码中用到的一些方法,进行下面总结:

  1. 字符串转换为字符数组,用toCharArray()
  2. 字符数组转换为字符串String,利用包装类的转换,用String.valueOf(char[] data, int offset, int count),后面的offset和count参数表示从[offset,count)范围,是左闭右开的,因此右侧要取top+1
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值