1047. 删除字符串中的所有相邻重复项
答案整理 加深记忆 便于复习!
文章目录
- 题目描述
- 方法:栈
题目描述
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例:
输入:“abbaca”
输出:“ca”
解释: 例如,在 “abbaca” 中,我们可以删除 “bb”,由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 “aaca”,其中又只有 “aa”, 可以执行重复项删除操作,所以最后的字符串为 “ca”。
提示:
1 <= S.length <= 20000
S 仅由小写英文字母组成。
方法:栈
充分理解题意后,我们可以发现,当字符串中同时有多组相邻重复项时,我们无论是先删除哪一个,都不会影响最终的结果。因此我们可以从左向右顺次处理该字符串。
而消除一对相邻重复项可能会导致新的相邻重复项出现,如从字符串 abba 中删除 bb 会导致出现新的相邻重复项 aa 出现。后出现的字符串要先进行判断,这和20. 有效的括号有异曲同工之妙,可以用栈来解决问题。我们只需要遍历该字符串,如果当前字符和栈顶字符相同,我们就贪心地将其消去,否则就将其入栈即可。
C++代码
在下面的 C++ 代码中,由于 std::string 类本身就提供了类似「入栈」和「出栈」的接口直接把不要的元素完全丢弃了,因此我们直接将需要被返回的字符串作为栈即可。对于其他的语言,如果字符串类没有提供相应的接口,则需要在遍历完成字符串后,使用栈中的字符显式地构造出需要被返回的字符串。如c语言通过’\0’作为结束符截断原来的字符串。
class Solution
{
public:
string removeDuplicates(string S)
{
string stk;
for (char ch : S)
{
if (!stk.empty() && stk.back() == ch)
{
stk.pop_back();
}
else
{
stk.pop_back(ch);
}
}
return stk;
}
};
C语言
下面程序用到了‘\0’对字符串数组进行截断。数组‘\0’后的字符对与字符串来说不再有效。
C语言字符串结束符’\0’
关于c语言字符串的讨论
char* removeDuplicates(char* S)
{
int n = strlen(S);//strlen 是一个函数,它用来计算指定字符串 str 的长度,但不包括结束字符'\0'
//真正在实际项目中,应该给i在主函数中定义char* stk
//并且通过函数参数传入函数,在函数中实现malloc操作
//这样在主函数中调用完该函数并使用完stk后,在主函数结尾可以对该块空间实现free(stk)
char* stk = malloc(sizeof(char)*(n + 1));
int retSize = 0;
for (int i = 0; i < n; i++)
{
if (retSize > 0 && stk[retSize - 1] == S[i])
{
retSize--;
}
else
{
stk[retSize++] = S[i];
}
}
//字符串总是以'\0'作为串的结束符。
//因此当把一个字符串存入一个数组时,也把结束符 '\0'存入数组,并以此作为该字符串是否结束的标志。
stk[retSize] = '\0';//'\0'后的数组元素不再有效
return stk;
}
复杂度分析
时间复杂度:O(n),其中 n 是字符串的长度。我们只需要遍历该字符串一次。
空间复杂度:O(n) 或 O(1),取决于使用的语言提供的字符串类是否提供了类似「入栈」和「出栈」的接口。注意返回值不计入空间复杂度。