1140 Look-and-say Sequence (20 分) 全网最细 题目详解 翻译 完整代码 PAT甲级真题解析

预备知识:

题目翻译:

Look-and-say 是一个整数序列:
D, D1, D111, D113, D11231, D112213111, …
其中D是属于 [0, 9] 的一个整数。第 (n+1) 个数是对第n个数的描述。
例如:
第二个数字 (D1) 的意思是第一个数字中有一个D;
第三个数字 (D111) 的意思是第二个数字中有一个D (D1) 和一个1 (11) ;
第四个数字 (D113) 的意思是第三个数字中有一个D (D1) 和三个1 (13) ;
第五个数字 (D11231) 的意思是第四个数字中有一个D (D1) 、两个1 (12) 和一个3 (31) ;

难点单词:

sequence 一系列 ; 一连串 ; 顺序 ; 次序 ;
nth 第n个的,第n次的

输入格式:

每个输入文件包含一个测试用例,其中给出一个范围 [0, 9] 的整数 D 和一个正整数 N (≤ 40) ,之间用空格隔开。

输出格式:

在一行中输出第n个数字的内容。

输入样例:

1 8

输出样例:

1123123111


题目解析:

其实题目不难,只不过解析写的很详细~如果想完全理解本道题的话,可以耐心读下去。

字符串处理题,简单题,稍微理清思路就能做出来。
随便举一个简化版的例子,例如 s = “122334” ,顺序遍历每一个字符。
我们需要两个变量,① 变量 (t) 存储当前正在计数的字符,② 变量 (count默认0) 存储当前字符的连续个数。

  1. 遍历 s[0] = “1” ,当前字符 “1”当前字符个数 1 个
  2. 遍历 s[1] = “2” ,与上一个字符不相同,当前字符 “2” ,当前字符连续个数 1 个;
  3. 遍历 s[2] = “2” ,与上一个字符相同,当前字符 “2”当前字符连续个数 2 个
  4. 遍历 s[3] = “3” ,与上一个字符不相同,当前字符 “3” ,当前字符连续个数 1 个;
  5. 遍历 s[4] = “3” ,与上一个字符相同,当前字符 “3”当前字符连续个数 2 个
  6. 遍历 s[5] = “4” ,与上一个字符不相同,当前字符 “4”当前字符连续个数 1 个

你会发现,带有删除线 的数字都被输出了,而它们输出的位置都有一些共同的特点(认真思考一下)。

所以这一轮循环得到的结果应该是: “11223241” 。

是不是看起来很简单?没错,这样梳理一遍后,只需要在合适的位置将字符和字符个数保存下来,最后重新赋给原字符串,不断进行 n-1 次循环就可以了~

逻辑梳理:

所以应该在什么时候保存字符和字符连续个数呢?
这里有很多选择,我的选择是:除特殊情况外,在字符个数归1(发生改变)之后保存新字符,在字符个数归1之前保存个数
在这里插入图片描述

这句话看起来可能比较难懂,你可以将它带入上面的例子再推导一遍就明白了~
这里的特殊情况指的是:

  1. 字符串的第一个元素 s[0] 没有前驱元素,无法进行比较;
  2. 字符串的最后一个元素如果与倒数第二个相同,则可能错过输出的机会。

你需要针对这些情况特殊处理。

参考代码:

不要觉得代码长就很难,其实逻辑很简单,分析一遍就懂了。

#include <iostream>
using namespace std;

int main() {
    string s;
    int n, count = 0;
    cin >> s >> n;
    for(int cnt = 1; cnt < n; cnt++) {
        string t;
        count = 0;
        for(int i = 0; i < s.length(); i++) {
            if(i == 0) { // 对第一位数字单独处理
                t += s[i]; // 存储当前字符
                count++;
            } else {
                if(s[i] == s[i - 1]) { // 如果当前位和上一位相等
                    count++; // 计数+1
                } else { // 当前位和上一位不等
                    t += to_string(count); //存储上一位字符的个数
                    count = 1; // 计数归1
                    t += s[i]; // 存储当前字符
                }
            }
            if(i == s.length() - 1) { // 对最后一位数字单独处理
                t += to_string(count);
            }
        }
        s = t;
    }
    cout << s << endl;
    return 0;
}

全部通过
在这里插入图片描述

最后附上柳神的参考代码,我这榆木脑袋肯定想不出这么好的代码。

#include <iostream>
using namespace std;
int main() {
    string s;
    int n, j;
    cin >> s >> n;
    for(int cnt = 1; cnt < n; cnt++) {
        string t;
        for(int i = 0; i < s.length(); i = j) {
            for(j = i; j < s.length() && s[i] == s[j]; j++);
            t += s[i] + to_string(j - i);
        }
        s = t;
    }
    cout << s;
    return 0;
}

共勉

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值