返回
外观数列通俗解法:玩转数列描述数列,攻克LeetCode第38题
前端
2023-10-15 17:40:15
问题引入
大家好,今天我们来谈谈外观数列。外观数列是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的。例如,外观数列的前 5 项如下:
1
11
21
1211
111221
可以发现,外观数列中的每一项都是由相邻数字的个数构成的。例如,第二项 11 是由两个 1 构成的,第三项 21 是由一个 2 和一个 1 构成的,第四项 1211 是由一个 1、一个 2 和两个 1 构成的,第五项 111221 是由三个 1、两个 2 和一个 1 构成的。
思路分析
现在,让我们来考虑一下如何求解外观数列的第 n 项。我们可以采用递归或递推的方法来解决这个问题。
递归方法
递归方法是通过将问题分解成更小的子问题来解决问题的。在这种情况下,我们可以将求解外观数列第 n 项的问题分解成求解外观数列第 n-1 项的问题。
例如,要求解外观数列第 5 项,我们可以先求解外观数列第 4 项。外观数列第 4 项是 1211。然后,我们可以将 1211 成 “一个 1、一个 2 和两个 1”。最后,我们将 “一个 1、一个 2 和两个 1” 翻译成数字形式,得到 111221。
递推方法
递推方法是通过从初始值开始,一步一步地推导出最终结果的方法。在这种情况下,我们可以从外观数列的第一项 1 开始,然后一步一步地推导出外观数列的每一项。
例如,要推导出外观数列的第五项,我们可以先推导出外观数列的第四项。外观数列的第四项是 1211。然后,我们可以将 1211 描述成 “一个 1、一个 2 和两个 1”。最后,我们将 “一个 1、一个 2 和两个 1” 翻译成数字形式,得到 111221。
代码实现
def count_and_say(n):
"""
计算外观数列的第 n 项。
参数:
n: 一个正整数。
返回:
外观数列的第 n 项。
"""
# 如果 n 等于 1,则返回 1。
if n == 1:
return "1"
# 否则,递归计算外观数列的第 n-1 项。
else:
prev = count_and_say(n-1)
# 将外观数列的第 n-1 项描述成 “相邻数字的个数构成的字符串”。
description = ""
count = 1
for i in range(1, len(prev)):
if prev[i] == prev[i-1]:
count += 1
else:
description += str(count) + prev[i-1]
count = 1
description += str(count) + prev[-1]
# 将 “相邻数字的个数构成的字符串”翻译成数字形式。
result = ""
for i in range(0, len(description), 2):
result += description[i] * int(description[i+1])
return result
# 测试代码
print(count_and_say(1)) # 输出:1
print(count_and_say(2)) # 输出:11
print(count_and_say(3)) # 输出:21
print(count_and_say(4)) # 输出:1211
print(count_and_say(5)) # 输出:111221
总结
通过本文,我们学习了外观数列的定义和求解方法。我们还学习了如何使用递归或递推的方法来解决问题。希望本文对您有所帮助。