计蒜客“伯爵说”问题(Count-And-Say)
“伯爵说”序列如下:1,11,21,1211,111221,…。其1
读作one 1
或者11
。11
读作two 1s
或者21
。21
读作one 2,one 1
或者1211
。
输入格式
多组输入,读到文件结束。每组输入给定一个整数 n(1≤n≤30)。
输出格式
输出第 n 个序列。注意,整数序列以字符串的形式表示。
样例输入
6
样例输出
312211
提示:
类似于求“斐波那契”数列的第 n 项哦~
这道题目其实不难解,后一项的值来自于前一项,有点类似于斐波那契数列,但是又不像。
关于此题的思路,就是用while从字符串的开头(i=0)开始,逐一向下判断,一直到i+1项为’\0’为止,如果i+1项的值等于第i项的值的话,那么i++,然后继续向下判断,直到第i项的值不再等于i++。然后就把这个数字重复的次数和数字再另一个字符串内保存起来,再把计数的变量初始化,i++,然后继续判断。
考虑到最后的数字可能没法保存,因此在while的外部再单独保存一遍。
以下就是我自己写的代码,已经添加了超级多的注释。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *CountAndSay(int n);//执行Count And Say
void CountSay(char *str1,char *str2);//得到每次CountSay后的结果
void Solve();
int main()
{
Solve();
return 0;
}
void Solve()
{
int n;//存储CountSay的次数
while(scanf("%d",&n)!=EOF)//一直输入到文件尾
{
printf("%s\n",CountAndSay(n));//将最后的结果打印出来
}
}
char *CountAndSay(int n)
{
char *str1,*str2;
str1=(char*)malloc(sizeof(char)*99999);//给str1一个较大的内存
str2=(char*)malloc(sizeof(char)*99999);//给str2一个较大的内存
memset(str1,0,99999);//给str1初始化
memset(str2,0,99999);//给str2初始化
strcpy(str1,"1");//给str1初始化为'1'的开始
for(int i=1;i<n;i++)//由于'1'是第一次Say的内容,因此循环n-1次
{
CountSay(str1,str2);//进行一次CountSay,并把结果存储到str2内
strcpy(str1,str2);//使str1的内容等于str2的内容,完成一次CountSay
}
free(str2);//释放掉无用的str2的内存
return str1;//返回最后一次CountSay的结果
}
void CountSay(char *str1,char *str2)
{
int count=1,i=0,j=0;//count用于存储相同数字出现的次数,最少1次。i是校验到的str1的位置,j是在str2添加的位置
while(str1[i+1]!='\0')//如果str1[i+1]的内容为'\0'就跳出循环
{
if(str1[i]==str1[i+1])//判断str1在i处的字符是否和i+1处的相等,相等count+1
{
i++;//向后移一位
count++;//重复数字的个数+1
}
else
{
str2[j++]=count+'0';//第一位是相同数字出现的次数,先赋值然后j++;
str2[j++]=str1[i];//第二位是重复的数字,先赋值然后j++;
i++;//向后移一位
count=1;//count初始化
}
}
//以下两行代码用于添加最后的一个重复数字,如1121,添加的是最后一个1的出现次数和数字。
str2[j++]=count+'0';//第一位是相同数字出现的次数,先赋值然后j++;
str2[j++]=str1[i];//第二位是重复的数字,先赋值然后j++;
}
谢谢观看