codeforces 600C(贪心)

http://codeforces.com/problemset/problem/600/C

题意:给你一个字符串,你可以改变它的任意字符,且可以任意调换字符顺序,输出字符改变次数最少的字典序序最小的字符串。(改变顺序次数不计)。

思路:记录所有字符出现的次数,从小到大,当出现次数为奇数时,找到最右边一个出现次数为奇数的字符,左边字符数+1,右边字符数-1。处理到最后一定会是最多只存在一个出现次数为奇数的字符。然后从a到z输出一下就是,注意aabbbcc输出abcbcba。

/*
           ┏┓   ┏┓
      ┏┛┻━━━┻┗┓
      ┃       ┃
      ┃   ━   ┃
      ┃ ┳┛ ┗┳ ┃
      ┃       ┃
      ┃   ┻   ┃
      ┗━┓     ┏━┛
        ┃ 一  ┃
        ┃ 发  ┃
        ┃  A  ┃
        ┃  C  ┃
  ┏━━━━┛    ┃
 ┏┫          ┃
 ┗┓ ***         ┃
  ┗┓┏┳━━┓┏┏┛
   ┣┣┃   ┣┣┃
   ┗┻┛   ┗┻┛

*/
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <algorithm>
#include <math.h>
#include <vector>
#include <map>
#define LL long long
#define maxn 200005
using namespace std;
map<char,int>m;
int main()
{
    string s;
    cin>>s;
    for(int i=0;i<s.length();i++)
        m[s[i]]++;
    char tmp='0';
    for(int i=0;i<26;i++)
    {
        if(m[i+'a']%2==1)
        {
            int j=25;
            while(m[j+'a']%2==0&&i<j)j--;
//            if(i!=j&&m[j+'a']%2==1)
//            {
//                m[i+'a']++;
//                m[j+'a']--;
//            }
            if(i==j)
            {
                m[i+'a']--;
                tmp='a'+i;
            }
            else
            {
                m[i+'a']++;
                m[j+'a']--;
            }
        }
    }
    string ans;
    for(int i=0;i<26;i++)
    {
        if(m[i+'a']%2==0)
        {
            int cnt=m[i+'a']/2;
            for(int j=0;j<cnt;j++)
                ans.push_back(i+'a');
        }
    }
    if(tmp!='0')
        ans.push_back(tmp);
    for(int i=25;i>=0;i--)
    {
        if(m[i+'a']%2==0)
        {
            int cnt=m[i+'a']/2;
            for(int j=0;j<cnt;j++)
                ans.push_back(i+'a');
        }
    }
    cout<<ans<<endl;
}

猜你喜欢

转载自blog.csdn.net/prometheus_97/article/details/81196385