1047. 删除字符串中的所有相邻重复项

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),取决于使用的语言提供的字符串类是否提供了类似「入栈」和「出栈」的接口。注意返回值不计入空间复杂度。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙叙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值