题目:
解题:

运行结果:

解题过程:
第一步:读题目
「外观数列」是一个数字字符串序列,由递归公式定义。
countAndSay(1) = "1"
countAndSay (n) 是 countAndSay (n-1) 的行程长度编码。
行程长度编码(RLE):把一串字符串里,连续相同的一组字符,替换成【这一组有多少个】+【这个字符本身】。
规则:先数个数,再写这个数字。
第二步:验证规则
n=1 → "1" (题目给的起点)
countAndSay (2) 是 countAndSay (1) 的 RLE 编码。countAndSay (1) 是 "1"。
看 "1":连续 1 个 1。按 RLE,个数 + 字符 → "1"+"1" = "11"。所以 n=2 → "11"。
n=3:对 n=2 的 "11" 做 RLE。"11":连续 2 个 1。个数 2,字符 1 → "2"+"1" = "21"。n=3 → "21"。
n=4:对 n=3 的 "21" 做 RLE。
现在看字符串 "21":第一个字符是 2,后面紧跟着是 1,不相等。
第一组:1 个 2 → "12"
第二组:1 个 1 → "11"
拼接起来:"12"+"11" = "1211"。
第三步:带入程序思路
我们需要从第 1 项开始,一轮一轮生成,生成到第 n 项为止。
迭代,而不是递归。递归会一层一层往下调,n 大的时候栈容易爆,而且会重复计算。迭代更简单,保存上一轮的字符串,不断更新,每次基于上一轮生成新串。所以优先选迭代。
然后思考:每一轮内部,怎么把旧字符串转成新字符串(RLE 编码)?
假设旧字符串 s,我们要遍历 s,统计连续相同字符。
模拟遍历过程,拿例子 s="21"(n=3 的结果,用来生成 n=4):指针 i 从 0 开始,i=0,字符是 '2'。
1、当前字符 cur='2',计数器 count=1。
2、i 往后走一步,i=1,字符是 '1',不等于 cur。
→ 这一组结束了:count=1,字符 '2'。追加 "12" 到新字符串。
3、更新 cur='1',count 重置为 1。
4、i 再往后走一步,i=2,超出字符串长度,循环结束。
(循环结束的时候,最后这一组还没有追加到新字符串!
所以遍历完整个字符串之后,必须把最后一组的 count 和 cur 补上。)
整理成小步骤:给定旧字符串 s:
1、初始化 i=0。
2、while i < s 的长度:
a. 记录当前字符 cur = s i
b. count=1
c. i +=1
d. 只要 i 没越界,并且 s i==cur,count++,i++
e. 一组结束,把 count 和 cur 写入新字符串
3、遍历结束,新字符串加上结束符 '\0'