笔试题1 -- 吃掉字符串中相邻的相同字符(点击消除_牛客网)

吃掉字符串中相邻的相同字符

文章目录

题目链接: 点击消除_牛客网

题目重现

牛牛拿到了一个字符串。

他每次"点击",可以把字符串中相邻两个相同字母消除,例如,字符串 "abbc" 点击后可以生成 "ac"。
但相同而不相邻、不相同的相邻字母都是不可以被消除的。

牛牛想把字符串变得尽可能短。他想知道,当他点击了足够多次之后,字符串的最终形态是什么?
输入描述

一个字符串,仅由小写字母组成。(字符串长度不大于300000)

输出描述

一个字符串,为"点击消除"后的最终形态。若最终的字符串为空串,则输出0。

解法一:(基于 erase() 函数实现)

缺点:

  • 效率问题 :使用 erase() 函数会导致字符串中的元素频繁移动,特别是在字符串较长时,这会造成较大的性能开销。
  • 复杂的边界处理 :代码中需要多次检查迭代器是否到达字符串的末尾,这增加了代码的复杂性。

代码示例:

cpp 复制代码
void eatCharacters(std::string& s)
{
	auto cur = s.begin();
	auto pre = cur + 1;
	for (; pre != s.end(); pre++, cur++)
	{
		while (*cur == *pre)
		{
			bool cur_is_begin = (cur == s.begin()) ? true : false;
			auto cur_l = cur - 1;

			pre = s.erase(cur, pre + 1);
			if (pre == s.end()) { return; }		// 注意这里判断避免后面越界
			if (cur_is_begin)
			{
				cur = pre;
				pre++;
				if (pre == s.end()) { return; }		// 注意这里判断避免后面越界
			}
			else
			{
				cur = cur_l;
			}
		}
	}
}

void test() {
	std::string input;
	std::cin >> input; // 从标准输入读取字符串

	eatCharacters(input);
	if (input.size() == 0)
	{
		cout << 0 << endl;
	}
	else
	{
		std::cout << input << std::endl; // 输出最终状态
	}
}

提交截图:

评价:

时间复杂度:

  • 最坏情况下,每次 erase() 调用都可能导致整个字符串的复制,因此时间复杂度为 O(n^2),其中 n 是字符串的长度。

空间复杂度:

  • 由于直接在原字符串上操作,空间复杂度为 O(1)

实际运行时间:

  • 在字符串较短或者需要消除的字符对较少时,这种方法可能表现得相当快。
  • 在字符串较长且有大量相邻字符对需要消除时,性能会显著下降。

适用场景:

  • 当处理的字符串较短,且内存资源受限时,这种方法可能更合适。

解法二:(利用 栈 辅助实现)

缺点:

  • 空间复杂度:虽然时间复杂度有所优化,但是这种方法需要额外的空间来存储栈。

代码示例:

cpp 复制代码
void eatCharacters(std::string& s) {
	stack<char> st;

	for (auto e : s)
	{
		if (st.empty() || st.top() != e) { st.push(e); }
		else {
			st.pop();
		}
	}

	s.clear();
	while (!st.empty())
	{
		s = st.top() + s;
		st.pop();
	}
}

void test() {
	std::string input;
	std::cin >> input; // 从标准输入读取字符串

	eatCharacters(input);
	if (input.size() == 0)
	{
		cout << 0 << endl;
	}
	else
	{
		std::cout << input << std::endl; // 输出最终状态
	}

}

提交截图:

评价:

时间复杂度:

  • 由于每个字符只被处理一次,时间复杂度为 O(n)

空间复杂度:

  • 需要一个额外的栈来存储字符,最坏情况下空间复杂度为 O(n)

实际运行时间:

  • 对于任何长度的字符串,这种方法都能保持稳定的性能。
  • 在处理大量数据时,这种方法的性能优势更加明显。

适用场景:

  • 当处理的字符串非常长,或者需要频繁执行消除操作时,这种方法更为高效。

总结

​ 在选择解法时,应考虑问题的规模和性能要求。对于小规模数据,两种方法都可以工作得很好,但解法一可能更节省内存。对于大规模数据,解法二的性能优势将非常明显,尽管它需要更多的内存。在实际应用中,如果内存不是问题,推荐使用解法二,因为它提供了更好的时间效率和代码的可维护性。

执行消除操作时,这种方法更为高效。

相关推荐
孑渡1 小时前
【LeetCode】每日一题:跳跃游戏 II
python·算法·leetcode·游戏·职场和发展
ka2x1 小时前
订单折扣金额分摊算法|代金券分摊|收银系统|积分分摊|分摊|精度问题|按比例分配|钱分摊|钱分配
java·c语言·c++·python·算法·spring·spring cloud
职略3 小时前
负载均衡类型和算法解析
java·运维·分布式·算法·负载均衡
A22743 小时前
LeetCode 196, 73, 105
java·算法·leetcode
阿里巴巴P8资深技术专家4 小时前
Java常用算法&集合扩容机制分析
java·数据结构·算法
zengson_g5 小时前
当需要对大量数据进行排序操作时,怎样优化内存使用和性能?
java·数据库·算法·排序算法
爱上电路设计5 小时前
有趣的算法
开发语言·c++·算法
窜天遁地大吗喽5 小时前
每日一题~ (判断是否是合法的出栈序列)
c++
Kerry_68 小时前
2024年江苏省研究生数学建模科研创新实践大赛C题气象数据高精度融合技术研究论文和代码分析
算法·数学建模·matlab·数据分析
风啊雨8 小时前
刷题Day44|188.买卖股票的最佳时机IV、309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费
算法