依旧是庞果网上的一道题目,详情如下:
给定一个字符串,仅由a,b,c 3种小写字母组成。当出现连续两个不同的字母时,你可以用另外一个字母替换它,如 有ab或ba连续出现,你把它们替换为字母c; 有ac或ca连续出现时,你可以把它们替换为字母b; 有bc或cb 连续出现时,你可以把它们替换为字母a。 你可以不断反复按照这个规则进行替换,你的目标是使得最终结果所得到的字符串尽可能短,求最终结果的最短长度。输入:字符串。长度不超过200,仅由abc三种小写字母组成。 输出: 按照上述规则不断消除替换,所得到的字符串最短的长度。例如:输入cab,输出2。因为我们可以把它变为bb或者变为cc。
输入bcab,输出1。尽管我们可以把它变为aab -> ac -> b,也可以把它变为bbb,但因为前者长度更短,所以输出1。函数头部: C/C++ int minLength(const char *s); Java: public class Main { public static int minLength(String s); }
这道题目难度有三颗星吧,我的程序虽然通过了,但是我也不知道为什么要这么写,我是通过列举找规律才发现这个结论的。。。
解题方法:
1、统计三个字母a,b,c的个数,分别为Acount, Bcount , Ccount;统计字符串的长度strlen;
2、通过一系列的数学证明,可知输出结果仅为三种,即1、2或strlen:
若字符串中的字符均为a或b或c,那么输出strlen;
若Acount, Bcount , Ccount均为奇数,那么输出结果result = 2;
若Acount, Bcount , Ccount均为偶数,那么输出结果result = 2;
若Acount, Bcount , Ccount有且仅有一个为偶数,那么输出结果result = 1;
若Acount, Bcount , Ccount有且仅有一个为奇数,那么输出结果result = 1;
#include <stdio.h>
#include <stdlib.h>
int ISeven(int n)
{
if(n % 2 == 0) return 1;
else return 0;
}
int minLength(const char *s)
{
int Acount = 0, Bcount = 0, Ccount = 0, iterCount = 0 , Strlen = 0;
for(iterCount = 0; s[iterCount] != '\000'; iterCount++)
{
switch(s[iterCount])
{
case 'a': Acount++; break;
case 'b': Bcount++; break;
case 'c': Ccount++; break;
}
Strlen++;
}
if(Acount == Strlen || Bcount == Strlen || Ccount == Strlen )
{
return Strlen;
}
printf("a:%d b:%d c:%d len = %d\n",Acount,Bcount,Ccount,Strlen);
switch(ISeven(Acount) + ISeven(Bcount) +ISeven(Ccount))
{
case 0: return 2;
case 1: return 1;
case 2: return 1;
case 3: return 2;
default: return 0;
}
}
int main(void)
{
int result = 0;
result = minLength("cccabcc");
printf("the minlen is %d\n",result);
return 0;
}
注:本博客与在博客园上的博客相同,且均为同一博客主所撰写。