1047. 删除字符串中的所有相邻重复项
给出由小写字母组成的字符串 S
,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例:
输入:"abbaca"
输出:"ca"
解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。
提示:
1 <= S.length <= 20000
S
仅由小写英文字母组成。
class Solution {
public:
string removeDuplicates(string s) {
int i = 0;
stack<char> my_stack; // 定义一个栈
while (i < s.size()) { // 遍历字符串中的每个字符
if (!my_stack.empty() && my_stack.top() == s[i]) { // 如果当前字符与栈顶元素相同,说明出现了重复字符
my_stack.pop(); // 将栈顶元素弹出
} else { // 如果当前字符与栈顶元素不同,将其压入栈中
my_stack.push(s[i]);
}
i++;
}
string result = ""; // 定义保存结果的字符串
while (!my_stack.empty()) { // 将栈中元素放到result字符串汇总
result += my_stack.top();
my_stack.pop();
}
reverse (result.begin(), result.end()); // 此时字符串需要反转一下
return result;
}
};
一个小细节:result += my_stack.top();
和 result = my_stack.top() + result;
性能上的差异
result = my_stack.top() + result;
实际上会先创建一个中间字符串对象来保存新的字符串,然后再将这个字符串对象赋值给result
。而 result += my_stack.top();
则可以直接在原字符串对象上追加新的字符,相比之下更加高效,也更加符合代码逻辑。
class Solution {
public:
string removeDuplicates(string s) {
int i = 0;
stack<char> my_stack; // 定义一个栈
while (i < s.size()) { // 遍历字符串中的每个字符
if (!my_stack.empty() && my_stack.top() == s[i]) { // 如果当前字符与栈顶元素相同,说明出现了重复字符
my_stack.pop(); // 将栈顶元素弹出
} else { // 如果当前字符与栈顶元素不同,将其压入栈中
my_stack.push(s[i]);
}
i++;
}
string result = ""; // 定义保存结果的字符串
while (!my_stack.empty()) { // 将栈中的元素依次取出,构造返回结果字符串
result = my_stack.top() + result;
my_stack.pop();
}
return result; // 返回去重后的字符串
}
};
这样写看起来很简单,不用反转字符串,但是性能却大大折扣,执行的时候会超过时间限制。
可以看到,这个测试用例非常长,最后运行超出时间限制。