题目来源:http://hero.pongo.cn
回文字符串是指从左到右和从右到左相同的字符串,
现给定一个仅由小写字母组成的字符串,你可以把它的字母重新排列,以形成不同的回文字符串。
输入:非空仅由小写字母组成的字符串,长度不超过100;
输出:能组成的所有回文串的个数(因为结果可能非常大,输出对1000000007取余数的结果)。
例如:输入"aabb" 输出为2(因为“aabb”对应的所有回文字符串有2个:abba和baab)
我的分析:
1常规思考a 实现步骤:
(1) 找出输入字符串的各种排列情况
(2)然后判断该字符串长度是回文字符串
b 算法分析:嵌套循环 100次
输入字符串的长度是n=100 组合情况 100!=9.332622e+157(看不懂,请教大神) 10!=3628800(百万)
如果一个字符串长度 n=50 不是回文串 太浪费 不合适!
测试分析
1 输入“aabb” 长度是 4 偶数 输出:abba baab 字符都是成对的出现的,因此所有字符出现的次数为偶数
2 输入 “aak” 长度是 3 奇术 输出 aka 并且这个奇数次的字符一定在出现在中间位置 出现唯一奇数次的字符
满足组合成回文字符串的条件是:
1 奇数次的字符个数<=1 如果大于1 肯定不是字符串 (补充:相同的字符除外)
2 对称出现 公式 S[i] =S[n-1-i] 前半部分和后半部分是一样的
只需要考虑前n/2个字符的组合情况!(s是回文字符串 n是回文字符字符串的长度)
[问题 前n/2 组合情况如何计算]
根据组合定义 相同元素组组合结果是一样的 n/2 最大情况就是不同元素组合结果
因为字符串的长度是26 等价于求组合情况
3 改进后的实现步骤:
(1) 判断是否串是是否满足 回文字符串
(2) 字符串组n/2 组合情况 (26!=4.0329146e+26 int返回 -2147483648到2147483648 )
代码实现:
** 题目:能组成的所有回文串的个数
**/
int palindrome(const char *s)
{
const char *pTemp=s; // invalid conversion from 'const char*' to 'char*'
int iLength=0;
int CharArr[26];
for( int i=0;i<26;i++)
{
CharArr[i]=0;
}
int iResult=1;
// 判断字符出现的次数 index=0 是‘a’ 出现的次数CharArr[0] index=1是‘b’出现的次数CharArr[1]
printf("input: %s\n",pTemp);
while(*pTemp!='\0')
{
//CharArr[*pTemp-'a']++;
CharArr[*pTemp-'a']++;
printf("key=%c,index=%d,value=%d \n",*pTemp,*pTemp-'a',CharArr[*pTemp-'a']);
pTemp++;
}
//判断字符串是否满足回文字符串并且统计不同字符串的个数
int iTemp=0;//记录奇数的个数
for( int i=0;i<26;i++)
{
if(CharArr[i]>0 && 0 !=CharArr[i]%2)
{ //计算奇数的个数
iTemp++;
}
if(iTemp>1)
{
printf(" 奇数的个数=%d \n",iTemp);
return 0;
}
//统计偶数的个数
if(CharArr[i]>0 && 0 ==CharArr[i]%2)
{
iLength++;
//printf("key=%d,value=%d \n",i,pTemp[i]);
}
}
//计算n的阶乘 n!
for( int i=1;i<=iLength;i++)
{
iResult=iResult*i%1000000007;
}
return iResult;
}
测试分析:
case 1 输入“aaaaa” 输出 0 原来 求n!i从0开始的4!=4*3*2*1*0=0
case 2 输入“aak” 输出 2 错误 原因:数次的字符一定在出现在中间位置 排除奇数
case 3 输入“aabbccddeeffggkkjjjmmpp” 输出 3628800 结果怎么这么大 不敢相信了。
发现和网上 参考:http://zh.wikipedia.org/wiki/%E5%B8%8C%E5%B0%94%E6%8E%92%E5%BA%8F 分析有出入
不知道是否正确! 发现问题 请微信我多谢!
@王传义 @一叶舟
微信:wang_cyi