题目:3035. 回文字符串的最大数量
方法一:先统计出所有字符出现的次数。然后将字符串的长度按升序排序。接着就可以模拟构造回文字符串。细节看注释
class Solution {
public:
int maxPalindromesAfterOperations(vector<string>& words) {
int a[30];
memset(a,0,sizeof a);
vector<int> v;
//统计出所有字符出现的次数
for(int i=0;i<words.size();i++){
for(auto x:words[i]){
a[x-'a']++;
}
v.push_back(words[i].size());
}
//统计出,单个字符和双个字符的次数
int ct1=0,ct2=0;
for(int i=0;i<26;i++){
if(a[i]){
if(a[i]%2){
ct1++;
ct2+=a[i]-1;
}else{
ct2+=a[i];
}
}
}
//将字符串的长度按升序排序
sort(v.begin(),v.end());
int ans=0;
for(int i=0;i<v.size();i++){
//如果是奇数长度
if(v[i]%2){
//单个字符还有多余
if(ct1){
//且双个字符也足够
if(ct2>=v[i]-1){
ans++;
ct1--;
ct2=ct2-(v[i]-1);
}
}else{
//单个字符没有多余,且双个字符拆开一对,还是足够
if(ct2-2>=v[i]-1){
ans++;
ct1++;
ct2=ct2-2-(v[i]-1);
}
}
}else{
//如果是偶数长度
//且双个字符也足够
if(ct2>=v[i]){
ans++;
ct2-=v[i];
}
}
}
return ans;
}
};
方法二:统计出所有字符的数量总和sum,然后减去数量为奇数的字符种类。最后进行回文字符串的构造,细节看注释。
class Solution {
public:
int maxPalindromesAfterOperations(vector<string>& words) {
//记录出字符出现的奇偶数状态
int sta=0;
//统计出所有字符的数量总和
int sum=0;
vector<int> v;
for(int i=0;i<words.size();i++){
for(auto x:words[i]){
sum++;
sta=sta^(1<<(x-'a'));
}
v.push_back(words[i].size());
}
//减去数量为奇数的字符种类
for(int i=25;i>=0;i--){
if(sta>>i&1) sum--;
}
int ans=0;
//将字符串的长度按升序排序
sort(v.begin(),v.end());
//对于奇数长度的字符串,只需要考虑除中间字符的两侧。而字符总数的数量是确定的,减去数量为奇数的字符种类,剩下的都是成对字符的总数量。接着只需要考虑这些成对的字符是否可以组成回文字符串即可。
//原理就是:单个字符可以由偶数个字符拆分得到,但是偶数字符是无法增加的。
for(auto x:v){
//这里只需要考虑字符串长度的偶数部分
sum-=x/2*2;
if(sum<0) break;
ans++;
}
return ans;
}
};