AI刷题之相邻重复字母删除问题 | 豆包MarsCode AI刷题

162 阅读3分钟

“相邻重复字母删除问题”题目要求

一、问题描述

小M拿到了一个由小写字母组成的字符串 s。她发现可以进行一种操作:选择两个相邻且相同的字母并删除它们。她可以在 s 上反复进行此操作,直到无法再删除任何字母。

请返回最终处理完所有重复项删除操作后的字符串。可以保证返回的答案是唯一的。

二、测试样例

样例1:

输入:s = "abbaca"
输出:'ca'

样例2:

输入:s = "azxxzy"
输出:'ay'

样例3:

输入:s = "a"
输出:'a'


三、题目解析

3.1代码思路

  1. 初始化栈
Stack<Character> stack = new Stack<>();

一个栈被用来存储字符,栈的性质(后进先出)非常适合处理相邻字符的消除操作。

  1. 遍历字符串
for (char c : s.toCharArray()) {

遍历字符串中的每一个字符,逐个处理。

  1. 判断与栈顶字符的关系
if (!stack.isEmpty() && stack.peek() == c) {
    stack.pop();
} else {
    stack.push(c);
}
  • 相邻字符相同:如果当前字符和栈顶字符相同,则从栈中移除栈顶字符(表示这两个字符被消除)。
  • 相邻字符不同:如果当前字符与栈顶字符不同,则将当前字符压入栈中。
  1. 拼接栈中的字符
StringBuilder result = new StringBuilder();
for (char c : stack) {
    result.append(c);
}

遍历栈中的剩余字符,按顺序拼接成最终字符串。

5.返回结果


return result.toString();

3.2详细代码

原始代码

import java.util.Stack;

public class Main {
    public static String solution(String s) {
        // 初始化一个栈
        Stack<Character> stack = new Stack<>();
        
        // 遍历字符串中的每个字符
        for (char c : s.toCharArray()) {
            // 如果栈不为空且栈顶元素与当前字符相同,弹出栈顶元素
            if (!stack.isEmpty() && stack.peek() == c) {
                stack.pop();
            } else {
                // 否则,将当前字符压入栈中
                stack.push(c);
            }
        }
        
        // 将栈中的字符拼接成字符串
        StringBuilder result = new StringBuilder();
        for (char c : stack) {
            result.append(c);
        }
        
        return result.toString();
    }

    public static void main(String[] args) {
        System.out.println(solution("abbaca").equals("ca"));
        System.out.println(solution("azxxzy").equals("ay"));
        System.out.println(solution("a").equals("a"));
    }
}

改进代码

import java.util.Stack;

public class Main {
    public static int solution(int N, int[] p) {
        int totalDiscount = 0;
        Stack<Integer> stack = new Stack<>();

        for (int i = 0; i < N; i++) {
            // Pop elements from stack while they are greater than current price
            while (!stack.isEmpty() && p[stack.peek()] > p[i]) {
                stack.pop();
            }

            // If stack is not empty, top of the stack is the nearest smaller or equal price
            if (!stack.isEmpty()) {
                totalDiscount += p[stack.peek()];
            }

            // Push current index onto the stack
            stack.push(i);
        }

        return totalDiscount;
    }

    public static void main(String[] args) {
        System.out.println(solution(5, new int[]{9, 4, 5, 2, 4}) == 6);
        System.out.println(solution(4, new int[]{1, 2, 3, 5}) == 6);
        System.out.println(solution(4, new int[]{4, 3, 2, 1}) == 0);
    }
}



四、知识总结

代码涉及到的编程知识如下:

  • 基于栈的消除机制

    • 栈是一种非常自然的数据结构,用于解决需要逆序回退的操作。通过栈的后进先出特性,可以有效处理类似“相邻元素消除”这样的问题。
  • 贪心策略

    • 每次遇到相邻相同的字符就立即消除,无需回溯或重新检查之前的字符。最终栈中的字符必然是符合题意的。
  • 时间复杂度和空间复杂度

    • 时间复杂度:遍历字符串,每个字符最多进栈和出栈一次,复杂度为 O(n),其中 nnn 是字符串长度。
    • 空间复杂度:栈的最大空间取决于输入字符串的长度,为 O(n)(最坏情况下没有重复字符)。
  • 适用场景

    • 这种算法可以扩展到类似问题,如括号匹配、多种类型相邻消除等。