题目地址:PAT乙1084.外观数列(20)
题目描述:
外观数列是指具有以下特点的整数序列:d, d1, d111, d113, d11231, d112213111, ...
它从不等于 1 的数字 d 开始,序列的第 n+1 项是对第 n 项的描述。比如第 2 项表示第 1 项有 1 个 d,所以就是 d1;第 2 项是 1 个 d(对应 d1)和 1 个 1(对应 11),所以第 3 项就是 d111。又比如第 4 项是 d113,其描述就是 1 个 d,2 个 1,1 个 3,所以下一项就是 d11231。当然这个定义对 d = 1 也成立。本题要求你推算任意给定数字 d 的外观数列的第 N 项。
题目解读:
这道题目说实话题目意思都有点难以理解,我在这简要解释一下。
1. d 只有一个d
2. d1 因为前面只有一个d,所以这里就写成d1,表示1个d
3. d111 这里是在第二个基础上,扩充而来,我在这添上一个辅助的分割符'|'帮助大家理解。那么第二个d1可以写成d|1,这样就分成了前后两个部分,前半部分是d,那么就是“一个d”,写成d1;后半部分是1,就是“一个1”,写成11。所以第三项就是d1|11即d111。
4. d113 分成d|111,那么就是“一个d”、“三个1”,第四项就写成d1|13
5. d11231 分成d|11|3,那么就是“一个d”、“两个1”、“一个3”。那第五项九尾d1|12|31.
总之一句话,就是把这个字符串进行分割,分割的方法为相同的数字为1块,然后对每一块描述,就是结果。到这里,可能有人已经看懂了我的例子,但发现去测试输入样例好像不对???在这里,我要说的是d用1带的话,第二项就是11,而不是"d1",所以不用分割成1|1,而是把11看成一个整体,这样出来的答案就是对的。
易错分析:
1. 第五个样例的N应该是40,这时字符数组的长度将很长,需要把数组开的大一点。
2. 用puts打印比printf快速,不然第五个样例就会超时。
解题过程:
使用3个数组,其中s为每一项的字符数组,temp2为每一个分段的结果,temp用于连接temp2所对应的结果。用strcpy对数组重新赋值,用strcat连接数组,即可。
程序:
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
int N;
char s[100000], temp[100000], temp2[100000];
scanf("%c %d", &s[0], &N);
for (int i = 0; i < N-1; i++)
{ /* cnt计算重复字母出现的次数 */
int len = strlen(s), cnt = 1;
for (int k = 0; k < len; k++)
{ /* 因为s[len]处为'\0',所以不用担心越界 */
if (s[k] == s[k+1])
cnt++; // 如果前后相等cnt++
else
{ /* 连接字符和次数 */
temp2[0] = s[k];
temp2[1] = cnt + '0';
strcat(temp, temp2);
cnt = 1;
}
}
strcpy(s, temp);
memset(temp, '\0', sizeof(temp)); // 清空temp
}
puts(s); // 使用puts比printf更高效,用printf第五个样例超时
}