1084 外观数列 (20 分)

博客围绕PAT中外观数列题展开,该题要求推算给定数字d的外观数列第N项。介绍了输入输出格式,解题思路涉及行程压缩编码,统计连续相同数字个数,讨论了用循环和递归实现,最终选用循环,还提及N为1时的特殊处理及易错点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 项。

输入格式:
输入第一行给出 [0,9] 范围内的一个整数 d、以及一个正整数 N(≤ 40),用空格分隔。

输出格式:
在一行中给出数字 d 的外观数列的第 N 项。

输入样例:

1 8

输出样例:

1123123111

解题思路:
Mara: 复杂,o((⊙﹏⊙))o
Jack:再复杂也是简单的叠加,拆开来看呗。外观描述,就是好像那个啥压缩算法一样,好像是行程压缩编码,就是这个样子。将连续的数字用数字和计数来编码。比如说“1111000” =》“1403”。
Mara: 让我推一推,像题目里面描述的如果d是1的话,那应该是:

1
11
12
1121
122111
112213
12221131
1123123111

还真是这样的,统计连续出现的相同数字的个数。hiahiahia
Jack: 然后这道题还有一个迭代的过程,用循环写就好了。
Mara: 那是不是还能用递归写啊,怎么不用递归啊,递归不是好写吗?
Jack: 我不太会写递归的,(✿◡‿◡),就用循环吧。然后 N 是 1 的话特殊处理一下, N不是 1 的时候,从第一项 变到 第N项, 一共需要 N - 1步。
Mara: ♪ d(^^*) 循环比递归跑的快呀,就用循环吧。
Jack: 好(^ o ^)/~


代码:

def main():
    d, N = (int(x) for x in input().split())
    # 接收整数d,范围是[0,9]以及一个正整数 N(≤ 40)。
    previous = str(d)
    # 将数字d变成字符串形式,便于后续处理。
    if N > 1:
        # 如果求得是 外观数列的 第2项或者任何后边的项。
        for x in range(N - 1):
            # 第一项与第N项之间的间隔是N-1,即只需要迭代N-1次。
            result = out_look(previous)
            # 迭代一次, result就是对previous的外观描述。
            previous = result
            # 将一次迭代的结果再次进行迭代。
    else:
        # 如果求得是外观数列的第一项,其实就是整数d自身。
        result = previous
    print(result)
    # 输出答案


def out_look(previous):
    """
       返回对previous的外观描述,输入为字符串,输出为字符串。
    """
    element = previous[0]
    # 取出previous 的第一项作为起始元素
    index = 0
    count = 1
    # index 指示当前位置, count 指示截止到当前位置element 元素共有多少。
    answer = ""
    # answer存储最终的 外观描述
    while True:
        # 我们在内部做判断,然后break出去。为什么这样做呢?因为在循环的内部我们
        # 需要试探着向后寻找同element相等的元素,而试探首先要保证不会造成数组
        # 越界。当然,这点可能不是一下子就能想到的。也就是说将判断放在循环内部是
        # 优化后的程序结构。
        index += 1
        # 试探着向后看
        if index < len(previous):
            # 没有越界,可以看
            if previous[index] == element:
                count += 1
                # element元素在重复,count记下数就可以了
            else:
                # 新的element已经出现,将旧的element和出现的次数记好
                answer += "{}{}".format(element, count)
                element = previous[index]
                count = 1
                # 新的element和新的count
        else:
            answer += "{}{}".format(element, count)
            # 不能再向后了,后面已经没有元素了。记录一下最后一个index和count
            break
            # 然后终止循环
    return answer
    # 返回答案


if __name__ == '__main__':
    main()


易错点:

  • N == 1 的时候,输出d自身。
  • d, d1, d111, d113, d11231, d112213111, ... 可以作为d != 1 时,前六项的公式。但是求公式再代入是不必要的,公式的存储(最多到第40项)是要占内存的哦,还不如直接求,又快又省。

总结:

Summer Breeze
summer-breeze

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花花生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值