【LeetCode学习笔记】38.外观数列

1. 题目描述

「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。前五项如下:

1.     1
2.     11
3.     21
4.     1211
5.     111221

1 被读作  "one 1"  ("一个一"),即 11。
11 被读作  "two 1s"  ("两个一"),即 21。
21 被读作  "one 2",  "one 1"  ("一个二" ,  "一个一"),即 1211。

给定一个正整数 n (1 ≤ n ≤ 30),输出外观数列的第 n 项。

注意:整数序列中的每一项将表示为一个字符串。

示例 1:

输入: 1
输出: "1"
解释:这是一个基本样例。

示例 2:

输入: 4
输出: "1211"
解释:当 n = 3 时,序列是 "21",其中我们有 "2" 和 "1" 两组,"2" 可以读作 "12",也就是出现频次 = 1 而值 = 2;                              类似 "1" 可以读作 "11"。所以答案是 "12" 和 "11" 组合在一起,也就是 "1211"。


2. 解题记录

2.1【2020/03/22 - 36ms - 85.51%】

        最初想到使用 list:cur_list、cur_num 和 next_list 来代表状态,朴素而直观地一步一步生成,直至外观数列第 n 项。

# 2020/03/22
class Solution:
    def countAndSay(self, n: int) -> str:
        if n == 1:
            return "1"       
        # 初始数列
        cur_list = [1]
        # 需操作次数
        for i in range(n-1):
            # 清空本次操作输出数列
            next_list = []
            # 初始化值状态
            cur_num = [0, cur_list[0]]  # 当前数的 个数+数值 
            # 遍历上次数列
            for num in cur_list:
                if num == cur_num[1]:
                    cur_num[0] += 1  # 当前数 个数+1
                else:
                    # 遇到新数值, 把前一个数的状态更新到本次输出数列中
                    next_list.append(cur_num[0])
                    next_list.append(cur_num[1])
                    # 更新当前数的 个数+数值
                    cur_num = [1, num]
            # 最后一个数只判断是否相同, 此处补更新到本次输出数列中
            next_list.append(cur_num[0])
            next_list.append(cur_num[1])
            # “本次输出数列”是下一次循环中的“上次数列”
            cur_list = next_list

        # 数字元素列表转字符串
        return "".join([str(i) for i in next_list])

2.1【2020/03/22 - 32ms - 94.92%】

        去掉 list 的中间形式,全程统一使用 string 减少类型转换带来的耗费。

class Solution:
    def countAndSay(self, n: int) -> str:
        if n == 1:
            return "1"       
        # 初始数列字符串
        cur_str = "1"
        # 需操作次数
        for i in range(n-1):
            # 清空本次操作输出数列字符串
            next_str = ""
            # 初始化值状态
            count = 0  # 当前数的个数
            cur_num = cur_str[0]  # 当前数的数值
            # 遍历上次数列字符串
            for num in cur_str:
                if num == cur_num:
                    count += 1  # 当前数 个数+1
                else:
                    # 遇到新数值, 把前一个数的状态更新到本次输出数列中
                    next_str += str(count)
                    next_str += cur_num
                    # 更新当前数的 个数+数值
                    count = 1
                    cur_num = num
            # 最后一个数只判断是否相同, 此处补更新到本次输出数列中
            next_str += str(count)
            next_str += cur_num
            # “本次输出数列”是下一次循环中的“上次数列”
            cur_str = next_str
        return next_str

        此外,无意中看到有实验表明,用 += 拼接 string 的速度,不及用 join() 拼接 list 为 string 的速度,具体参见:

        《Python字符串拼接效率比较》《Python中字符串连接,“+”的效率很低!》

        经观察,上述即为正常的次快和最快写法。当然,要是直接输出写好的 list 并索引之,速度固然是很快,但 。。。

发布了14 篇原创文章 · 获赞 12 · 访问量 720

猜你喜欢

转载自blog.csdn.net/qq_39478403/article/details/105209928
今日推荐