【相邻不同型贪心】LeetCode767 重构字符串
题解
通常直接思考最佳策略是十分困难的,我们不妨思考每一种情况需要如何处理:
-
整个字符串只有一种字符
若字符串长度为 ,那么字符串本身即为答案;
若字符串长度大于等于 ,那么不存在可行方案 -
整个字符串只有两种字符
,数量分别为
若字符 的数量 == 字符 的数量 ,明显字符 和字符 交替出现即可
若字符 的数量 > 字符 的数量 ,那么每两个字符 之间必须插入一个字符 ,也就是 。进一步思考, 可以大于 吗?答案是不行,因为无法为每两个字符 之间插入一个字符
若字符 的数量 < 字符 的数量 ,情况类似于 的情况
从只有两种字符的情况,易得到启发:出现次数最多的字符,每两个之间必须插入至少一个不同的字符 -
整个字符串有
种字符,第 种字符的数量为
由只有两种字符的字符串重构成功的方案来看,在有 种类字符的字符串中,需要首先处理出现次数最多的元素,不妨记出现次数为
如下图所示,至少需要在 个元素之间插入一个与左右相邻元素均不同的元素:
所以,只需要将
个出现次数最多的元素(若有多个出现次数最多的元素,任意选择其中一个即可)先依次放入位置 ,随后将剩下的全部元素,按种类依次从位置 填到为止 即可。
若 全部元素个数 - ,则无解,否则有解。
问:为什么维护出现次数最多的种类元素是可行的方案?
答:因为题目要求的是相邻两个元素不可相同,那么在字符串中全部种类的单种元素的出现次数都不会超过
参考代码
class Solution { public: string reorganizeString(string s) { string ans; vector<int> mp(26); for (auto &it: s) { mp[it - 'a'] ++; } int mx = 0, idx = 0, sum = 0; for (int i = 0; i < 26; ++ i) { if (mx < mp[i]) { mx = mp[i]; idx = i; } sum += mp[i]; } if (sum - mx >= mx - 1) { vector<vector<char>> v(mx); for (auto &it: v) { it.push_back('a' + idx); } mp[idx] = 0; int cur = 0; for (int i = 0; i < 26; ++ i) { while (mp[i] > 0) { v[cur].emplace_back('a' + i); cur = (cur + 1) % mx; -- mp[i]; } } for (auto &u: v) { for (auto &i: u) { ans.push_back(i); } } } return ans; } };
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库
· 【.NET】调用本地 Deepseek 模型