1.相邻重复字母删除问题
问题描述
小M拿到了一个由小写字母组成的字符串 s。她发现可以进行一种操作:选择两个相邻且相同的字母并删除它们。她可以在 s 上反复进行此操作,直到无法再删除任何字母。
请返回最终处理完所有重复项删除操作后的字符串。可以保证返回的答案是唯一的。
测试样例
样例1:
输入:
s = "abbaca"输出:'ca'
样例2:
输入:
s = "azxxzy"输出:'ay'
样例3:
输入:
s = "a"输出:'a'
2.解题思路
这个问题要求我们在给定的字符串中删除所有相邻的重复字母。每次我们遇到两个相邻且相同的字母时,我们需要删除这两个字母。删除操作将一直持续,直到无法再进行删除为止。
我们可以利用栈来模拟这一操作,因为栈具有“先进后出”(LIFO)特点,能很好地匹配相邻重复字母的删除过程。
步骤:
-
使用栈来处理问题:
- 栈是一种先进后出(LIFO)的数据结构。当我们遍历字符串中的每个字符时,我们可以将其逐个压入栈中。
- 每次处理字符时,我们检查栈顶的元素。如果栈顶元素和当前字符相同,意味着我们找到了一个相邻重复的字母,可以将栈顶元素弹出,表示删除这两个字符。如果栈顶元素与当前字符不同,说明没有找到相邻重复的字符,则将当前字符压入栈中。
-
栈的作用:
- 栈用于存储当前“未删除”的字符。当我们遇到相邻重复的字符时,它们就会被从栈中移除。
- 最终栈中保存的就是处理完所有相邻重复字母后的结果。
-
输出最终结果:
- 在遍历完所有字符后,栈中将只包含没有相邻重复字母的字符。我们可以通过遍历栈,将其内容拼接成一个字符串作为最终的输出。
3.代码实现
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")); // 应该输出 true
System.out.println(solution("azxxzy").equals("ay")); // 应该输出 true
System.out.println(solution("a").equals("a")); // 应该输出 true
}
}
这段代码通过栈来处理相邻重复字母删除的问题。首先,创建一个空栈用于存储字符。接着遍历字符串中的每个字符,当遇到与栈顶字符相同的字符时,就弹出栈顶字符,表示删除这两个相邻字符;如果栈顶字符与当前字符不同,则将当前字符压入栈中。遍历完成后,栈中的字符即为删除所有相邻重复字母后的结果,最后通过 StringBuilder 将栈中的字符拼接成一个字符串并返回。这个方法的核心思想是利用栈的先进后出特性,快速处理重复字符并模拟删除操作。
4.复杂度分析
-
时间复杂度:
O(n),其中n是字符串的长度。我们只需要遍历一次字符串,每个字符最多被压入栈一次,也最多被弹出一次。 -
空间复杂度:
O(n),栈最多存储所有字符,在最坏情况下,所有字符都是不相邻重复的,因此栈的空间需求是O(n)。