题解 | #E 小红的字符串重排#

小红的字符串重排

https://ac.nowcoder.com/acm/contest/92662/E

对于字符串重排问题,有解的情况当且仅当所有元素的出现次数不超过总元素个数的一半,因此首先记录每个元素的出现次数判断是否输出”-1“

int n(s.size());
std::map<char, int> m;
for (char c : s)
{
	++m[c];
	if (m[c] > n / 2)
	{
		std::cout << -1 << std::endl;
		return;
	}
}

然后关于元素如何重排,可以考虑贪心的策略,即遍历每个位置,将所有未排元素按剩余数量从大到小排序,在每个位置放下的元素为【出现次数最多且与原元素不同】的元素

// 将map中的数据拷贝到vector中,便于排序
std::vector<std::pair<char, int>> alphas(m.begin(), m.end());

std::string ans;
for (int i(0); i < n; ++i)
{
	std::sort(alphas.begin(), alphas.end(),
	[](std::pair<char, int> a, std::pair<char, int> b)
	{
		return a.second > b.second;
	});
	for (std::pair<char, int>& ci : alphas)
	{
		if (ci.first != s[i] && ci.second)
		{
			ans += ci.first;
			--ci.second;
			break;
		}
	}
}

然而这种贪心策略并不一定能得到答案
比如数据:aabbc
按照上述方式将输出:aabb
没错,只输出四个字母,因为当遍历到第五个位置时,未放置的元素只剩一个‘c’,且与原元素相同,因此该位置有空缺(比赛的时候没想到这种情况,只拿了210分)

然后我想到一种改进方法,上面提到,当所有元素的出现次数都不超过总个数一半时,必定有解
因此可以考虑,当上述贪心策略在某个位置无法正确放置元素时,可从已放置过的位置遍历,寻找一个元素与其换位,使得两个位置都能满足条件

std::string ans;
for (int i(0); i < n; ++i)
{
	std::sort(alphas.begin(), alphas.end(),
	[](std::pair<char, int> a, std::pair<char, int> b)
	{
		return a.second > b.second;
	});
	/*新增*/
  	bool find(false);
	for (std::pair<char, int>& ci : alphas)
	{
		if (ci.first != s[i] && ci.second)
		{
			ans += ci.first;
			--ci.second;
			/*新增*/
          	find = true;
			break;
		}
	}
	/*新增*/
  	if (!find)
	{
		for (int j(0); j < ans.size(); ++j)
		{
			if (ans[j] != s[i] && s[j] != s[i])
			{
				ans += ans[j];
				ans[j] = s[i];
				break;
			}
		}
	}
}

经过置换之后便可得到符合要求的重排字符串
完整代码附上

void solve(void)
{
    std::string s;
	std::cin >> s;
	int n(s.size());
	std::map<char, int> m;
	for (char c : s)
	{
		++m[c];
		if (m[c] > n / 2)
		{
			std::cout << -1 << std::endl;
			return;
		}
	}
	std::vector<std::pair<char, int>> alphas(m.begin(), m.end());
	std::string ans;
	for (int i(0); i < n; ++i)
	{
		std::sort(alphas.begin(), alphas.end(),
		[](std::pair<char, int> a, std::pair<char, int> b)
		{
			return a.second > b.second;
		});
		bool find(false);
		for (std::pair<char, int>& ci : alphas)
		{
			if (ci.first != s[i] && ci.second)
			{
				ans += ci.first;
				--ci.second;
				find = true;
				break;
			}
		}
		if (!find)
		{
			for (int j(0); j < ans.size(); ++j)
			{
				if (ans[j] != s[i] && s[j] != s[i])
				{
					ans += ans[j];
					ans[j] = s[i];
					break;
				}
			}
		}
	}
	std::cout << ans << std::endl;
} 
全部评论
orz
点赞 回复 分享
发布于 2024-11-19 14:46 湖南
orz
点赞 回复 分享
发布于 2024-11-19 14:47 湖南
orz
点赞 回复 分享
发布于 2024-11-19 14:47 湖南

相关推荐

2024-12-11 14:09
已编辑
中国海洋大学 数值策划
点赞 评论 收藏
分享
评论
4
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务