小C的回文博弈
问题描述
小C和小U在一场激烈的回文博弈中展开对决。游戏从一个初始字符串s开始,规则如下:
- 每个玩家轮流行动,每次行动都可以重新排列字符串。
- 如果通过重新排列能够形成一个回文串,游戏立即结束,当前玩家获胜。
- 如果无法形成回文串,玩家必须删除字符串中的一个字符,游戏继续。
小C总是先手,两人都使用最优策略,最终谁将赢得这场比赛呢?如果小C获胜则输出"C",小U获胜则输出"U"
测试样例
样例1:
输入:
s = "aab"
输出:'C'
样例2:
输入:
s = "abc"
输出:'C'
样例3:
输入:
s = "abcd"
输出:'U'
思路分析
-
统计字符出现次数:
- 使用一个数组或者哈希表来统计每个字符的出现次数。
-
判断回文条件:
- 计算出现次数为奇数的字符数量。
- 如果奇数次字符的数量为0或偶数,当前字符串可以重新排列成回文串。
具体思路
-
初始化数组和变量:
- 在
solution方法中,创建一个长度为 26 的整数数组sInt,用于统计每个小写字母出现的次数。每个位置对应一个小写字母,例如sInt[0]对应'a',sInt[1]对应'b'等等。 - 定义一个整数变量
odd,用于记录出现奇数次的字母的数量。
- 在
-
统计字符串中每个字母的出现次数:
- 通过第一个
for循环遍历输入的字符串s。对于字符串中的每个字符,通过s.charAt(i) - 'a'计算出该字符对应的数组索引。 - 将对应索引位置的数组元素加一,即
sInt[s.charAt(i) - 'a']++,统计每个字母在字符串中出现的次数。
- 通过第一个
-
统计出现奇数次的字母数量:
- 第二个
for循环遍历sInt数组。对于每个数组元素,如果该元素的值(即对应字母的出现次数)是奇数,就将odd变量加一,即if(sInt[i] % 2!= 0){ odd++; }。
- 第二个
-
根据奇数次字母数量判断结果:
- 根据
odd的值来决定返回的字符。如果odd为 0 或者odd是奇数,就返回'C',否则返回'U'。
- 根据
代码实现
public class Main {
public static char solution(String s) {
// write code here
int[] sInt = new int[26];
int odd = 0;
for(int i = 0; i < s.length(); i++){
sInt[s.charAt(i) - 'a']++;
}
for(int i = 0; i < sInt.length; i++){
if(sInt[i] % 2 != 0){
odd++;
}
}
if(odd == 0 || odd % 2 != 0){
return 'C';
}
return 'U';
}
public static void main(String[] args) {
System.out.println(solution("aab") == 'C');
System.out.println(solution("abc") == 'C');
System.out.println(solution("abcd") == 'U');
}
}
总结
一、数据结构的选择
- 数组:本题中,使用一个长度为 26 的整数数组来统计每个小写字母在字符串中的出现次数。可以直接通过字符的 ASCII 值减去
'a'的 ASCII 值来确定对应的数组索引,快速进行统计。
二、条件判断的准确性
- 奇数判断:通过判断统计数组中元素是否为奇数,来确定出现奇数次的字母数量。本题中,使用
sInt[i] % 2!= 0来判断元素是否为奇数。 - 复杂条件判断:最后根据出现奇数次的字母数量进行复杂的条件判断,确定返回的字符。本题中,使用
odd == 0 || odd % 2!= 0来判断返回'C'还是'U'。