贪心算法四
- 1.最长回文串
- 2.增减字符串匹配
- 3.分发饼干
- 4.最优除法
点赞👍👍收藏🌟🌟关注💖💖
你的支持是对我最大的鼓励,我们一起努力吧!😃😃
1.最长回文串
题目链接: 409. 最长回文串
题目分析:
给一个包含大小字母的字符串,从里面挑选出来一些字母构成一个最长回文串,然后返回它的长度。
算法原理:
我们可以先统计每个字符的个数,为什么先统计次数呢,我们发现构建的回文串从中间劈开后,相同的字符左边放一个右边放一个。把所有能用的字符能放就全部放那就是我们的贪心策略。
所以先统计每个字符出现的个数,然后以中间线为分割线左边放一个右边放一个。
上面是我们的总体思路,接下来考虑一下细节问题。字符可能是偶数个,也可能是奇数个。如果是偶数的话太好了全都放。但是如果是奇数个就有问题了,因为我们要左边放一个右边放一个要能对称,此时最贪心的想法就是奇数-1变成偶数然后放。
虽然上面把一左一右的搞定的,但是还是有一个小问题,回文串中间这个分割线也是可以摆一个字符,只要我们在统计字符个数的时候发现某个字符出现了奇数次,一左一右我们肯定会漏这一个字符,所以中间这里可以把这个字符加上。
所以我们策略出来了,如果偶数全部加上,如果是奇数 - 1 后在加上,所以情况都考虑完,在考虑中间这个地方能不能摆,取决于有没有出现一个字符出现奇数次,如果出现就在中间摆一个。
写代码的时候奇偶是可以放在一块写的,假设字符出现 x 次,ret += x / 2 * 2。因为 算 / 2 是一个向下取整 , 7 / 2 = 3, 3 * 2 =6,相当于就是7 - 1 = 6,如果是偶数 / 2 * 2 是不变的。
还有在最后要统计一下是否有个字符出现奇数次,其实也没有必要,其实用最后统计出来的ret和s.size()比较一下,如果小于 ret + 1,原因就是如果字符都出现偶数那么ret = s.size() 一左一右,如果小于那肯定有字符出现了奇数次。
class Solution {
public:
int longestPalindrome(string s) {
// 1.计数 -- 用数组模拟哈希表
int hash[127] = {
0};
for(auto ch : s) hash[ch]++;
// 2.统计结果
int ret = 0;
for(auto x : hash) ret += x / 2 * 2;
if(ret < s.size()) ++ret;
return ret;
}
};
2.增减字符串匹配
题目链接: 942. 增减字符串匹配
题目分析:
由范围 [0,n] 内所有整数组成的 n + 1 个整数的排列序列可以表示为长度为 n 的字符串 s ,其中:
如果 perm[i] < pe