38.报数

题目

报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:

  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"

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-and-say

解答

  1. 直推法
    类似斐波拉契,知道前几项找关系得到后项
def countAndSay(n):
    if n == 1:
        res = '1'
    if n == 2:
        res ='11'

    pre = '11'
    for i in range(3, n+1):
        res = ''
        cnt = 1  #
        length = len(pre)  # 知道上一级的len,遍历每个字符才能得到下一级的res
        for j in range(1, length):  # use range(1,) other than range(0,) in case out of range
            if pre[j-1] == pre[j]:
                cnt += 1
                # res += str(cnt) + pre[j-1]
                # if this order exists,
                # the way to output last one(last two nums different)number
                # or both last two(last two nums same)numbers are different

            else:
                res += str(cnt) + pre[j-1]  # one x (x is the num should be transfer)
                cnt = 1
        res += str(cnt) + pre[j]  # must write this order beyond loop
        pre = res
    return res

其实中心思想就是分两种情况考虑,一种是相连的数相同,一种是相连的数不相同。下一个报数就是上一个报数的变形。如果一个报数中相邻两个数字不同,变形后原来两数会变成四个数;如果两数相同,变形后仍然是两位数,如果连续三数或者更多数相同,变形后维持两数。
如果相邻两数相同,cnt++,res里加上cnt和要变形的这个数;如果不同,cnt=1,res里加上cnt和要变形的数。
一开始有点没懂为什么在里面的for循环外要加上res += str(cnt) + pre[j-1]而在pre[j-1] == pre[j]:中不加上这句话。
这主要针对最后两个数字。
若最后两数不同,则最后一个数(1)在for循环外变形(one 1)-> ‘11’;
若最后两(多)数相同,则最后两(多)个数在for循环内增加cnt的值,然后在for循环外一起变形。

  1. 递归
    每一个countAndSay(n)会得到一个报数,然后被下一个countAndSay(n+1)使用。
    def countAndSay(self, n: int) -> str:
        if n == 1:
            return '1'
        # 每次迭代都要初始化pre cnt res
        pre = ''      # 设初值,第一个数无法判断和后面的数是否相等
        cnt = 0       # 则第一个数字是和空字符比较,因为前方没有数字能比较
        res = ''

        for num in self.countAndSay(n-1):
            if num != pre:  # 比较后一个数字和前一个数字是否相等
                if cnt > 0:
                    res += str(cnt) + str(pre)
                cnt = 1  # 除了num = 第一个数时cnt = 0,其他时候都 = 1
                pre = num  # pre变成等会要变形数字的上一个数字
            else:
                cnt += 1
        res += str(cnt) + str(pre)  # 为了最后一个数或两个数的变形
        return res
  1. groupby方法

你可能感兴趣的:(38.报数)