“相邻重复字母删除问题”题目要求
一、问题描述
小M拿到了一个由小写字母组成的字符串 s。她发现可以进行一种操作:选择两个相邻且相同的字母并删除它们。她可以在 s 上反复进行此操作,直到无法再删除任何字母。
请返回最终处理完所有重复项删除操作后的字符串。可以保证返回的答案是唯一的。
二、测试样例
样例1:
输入:
s = "abbaca"
输出:'ca'
样例2:
输入:
s = "azxxzy"
输出:'ay'
样例3:
输入:
s = "a"
输出:'a'
三、题目解析
3.1代码思路
- 初始化栈:
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);
}
遍历栈中的剩余字符,按顺序拼接成最终字符串。
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)(最坏情况下没有重复字符)。
-
适用场景:
- 这种算法可以扩展到类似问题,如括号匹配、多种类型相邻消除等。