1、题目原文
问题描述
小C和小U在一场激烈的回文博弈中展开对决。游戏从一个初始字符串s开始,规则如下:
- 每个玩家轮流行动,每次行动都可以重新排列字符串。
- 如果通过重新排列能够形成一个回文串,游戏立即结束,当前玩家获胜。
- 如果无法形成回文串,玩家必须删除字符串中的一个字符,游戏继续。
小C总是先手,两人都使用最优策略,最终谁将赢得这场比赛呢?如果小C获胜则输出"C",小U获胜则输出"U"
测试样例
样例1:
输入:s = "aab"
输出:
'C'
样例2:
输入:s = "abc"
输出:
'C'
样例3:
输入:s = "abcd"
输出:
'U'
2、解题思路
想要构建一个回文字符串,比较关键的内容就是字符的数量的奇偶性,更具体来说,是数量为奇数的字符和数量为偶数的字符串。更进一步,可以分为奇数字符的数量的奇偶性(比如有3或4个数量为奇数的字符)和偶数字符的数量(比如有3或4个数量为偶数的字符)。
这道题可以理解为一种数学上的分情况讨论的题。
问题1:偶数的个数是否重要
举例来说,在一个字符串中,某几个数量为偶数的字符的具体数目为 2,2,2 或者2,2,2,2。对于这道题来说有没有区别呢?
答案是没有区别。我们假设B在修改偶数字符前处于优势地位(也就是可以取得最终的胜利),那么当A尝试去修改偶数字符,将其转换为奇数字符,(2,2,2,2 → 2,2,2,1)从而改变自己的获胜情况时,B可以立刻再对该偶数字符进行一次修改,从而继续维护自己的优势地位。(2,2,2,1→ 2,2,2,0),也就是说,对于参与操作的双方来说,无论偶数的数量是奇数还是偶数,都无法影响最终的结果,所以我们在进行统计的时候实际上就可以不用管这一部分的内容了。
问题2:奇数的个数是否重要
很重要,如果想要获胜,实际上就是最先将奇数的个数降为1或者0;
如果初始化时,奇数的个数就为0或者1,那么先发者直接就获得了胜利。
如果奇数的个数为奇数,那么在不断的将奇数转变为偶数的过程中,先发者最终会先达到奇数数量为1的情况,从而获得胜利。
如果奇数的个数为偶数,先发者在进行任意操作之后,就转换到了上面的情况,从而输掉比赛。
具体代码:
简单来说就是先统计奇数和偶数的字符,然后再统计奇数的个数,从而直接得到胜利者。
#include <iostream>
#include <vector>
#include <string>
#include <unordered_map>
using namespace std;
char solution(const std::string& s) {
// write code here
unordered_map<char,int > m;
for(int i=0;i<s.length();++i){
m[s[i]]++;
}
int countOdd = 0;
for(auto it:m){
if(it.second%2){
countOdd++;
}
}
char ans=' ';
if(countOdd==0 || countOdd ==1 || countOdd%2 ){
ans='C';
}
else{
ans='U';
}
return ans;
}
int main() {
std::cout << (solution("aab") == 'C') << std::endl;
std::cout << (solution("abc") == 'C') << std::endl;
std::cout << (solution("abcd") == 'U') << std::endl;
return 0;
}