class Solution {
public String removeDuplicates(String s) {
Stack<Character> stack = new Stack<>();
for (int i = 0; i < s.length(); i++) {
if (!stack.empty() && stack.peek() == s.charAt(i)) {
stack.pop();
} else {
stack.push(s.charAt(i));
}
}
int n = stack.size();
char[] ch = new char[n];
while (!stack.empty()) {
ch[--n] = stack.pop();
}
return new String(ch);
}
}
我的解分为两部分,第一部分是入栈匹配,第二个部分是出栈转为结果字符串。但是运行时间很长,有可以改进的部分。
String str = "";
while (!stack.empty()) {
str = stack.pop() + str;
}
return str;
改变第二部分,但是时间性能并没有提升
class Solution {
public String removeDuplicates(String s) {
StringBuilder res = new StringBuilder();
int inx = -1;
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (inx < 0 || res.charAt(inx) != ch) {
res.append(ch);
inx++;
} else {
res.deleteCharAt(inx--);
}
}
return res.toString();
}
}
本质上,String是一个不可变字符串,每一次对String操作的过程都是重新创建一个String字符串的过程。使用StringBuilder这个可变字符串对象大大提高了时间性能。
class Solution {
public String removeDuplicates(String s) {
char[] ch = s.toCharArray();
int slow = 0;
int fast = 0;
// 原地操作 slow指针指向新字符串尾部的下一个字符
while (fast < s.length()) {
ch[slow] = ch[fast];
// slow指针指向新字符串尾部
if (slow > 0 && ch[slow] == ch[slow - 1]) {
slow--;
//为什么要--,因为新字符串应该退出一个字符
} else {
slow++;
}
fast++;
}
return new String(ch, 0, slow);
}
}
原地操作,双指针发,之前也用过这种思路,快指针操作String s,慢指针操作新字符串。这里需要注意的是慢指针指向的是新字符串的下一个位置,在循环一开始,先把这个位置尝试填上字符,如果可以消掉,那慢指针后退一步。
String初始化可以指定字符数组的索引String(ch, 0, slow),[0,slow).