本篇使用c++
目录
1、题目链接
2、题目介绍
「外观数列」是一个数位字符串序列,由递归公式定义:
countAndSay(1) = "1"
countAndSay(n)
是countAndSay(n-1)
的行程长度编码。
行程长度编码(RLE)是一种字符串压缩方法,其工作原理是通过将连续相同字符(重复两次或更多次)替换为字符重复次数(运行长度)和字符的串联。例如,要压缩字符串 "3322251"
,我们将 "33"
用 "23"
替换,将 "222"
用 "32"
替换,将 "5"
用 "15"
替换并将 "1"
用 "11"
替换。因此压缩后字符串变为 "23321511"
。
给定一个整数 n
,返回 外观数列 的第 n
个元素。
示例 1:
输入:n = 4
输出:"1211"
解释:
countAndSay(1) = "1"
countAndSay(2) = "1" 的行程长度编码 = "11"
countAndSay(3) = "11" 的行程长度编码 = "21"
countAndSay(4) = "21" 的行程长度编码 = "1211"
3、解法
1) 理解题目和定义
首先,需要理解题目中的“外观数列”和“行程长度编码(RLE)”的概念。
- 外观数列是一个数位字符串序列,其中每个元素都是前一个元素的行程长度编码。
- 行程长度编码是一种字符串压缩方法,它通过计算连续相同字符的数量来压缩字符串。
例如,
给定字符串 "112223",其行程长度编码为 "213213",因为有两个'1',一个'2'(但这里实际上是连续的两个'2',所以编码为'22'),然后又是三个'2',最后是一个'3'。
但注意,这里我们实际上在编码时,每遇到一组连续相同的字符,就将其数量和该字符一起编码,而不是先编码字符再编码数量。所以,"112223" 正确的行程长度编码应为 "21321"。
2)实现步骤
a. 定义一个辅助函数
dispose(string x)
这个函数负责将输入的字符串
x
转换为它的行程长度编码。我们使用双指针法来遍历字符串,
left
指针指向当前正在处理的字符的起始位置,right
指针用于寻找与left
指针指向字符相同的连续字符的结束位置。每找到一组连续相同的字符,我们就将其数量(
right - left
)和字符本身拼接成一个新的字符串片段,并添加到结果字符串tmp
中。最后返回tmp
。string dispose(string x) { string tmp;//临时存放编码后的字符串 int n = x.size(); if (n == 1) { tmp.push_back('1'); tmp.push_back(x[0]); return tmp; } //双指针-->完成行程长度编码 int left = 0, right = 1; while (right < x.size()) { while (right < x.size() && x[right] == x[left]) { right++; } string ch = to_string(right - left); tmp += ch + x[left]; left = right; } return tmp; }
b. 实现
countAndSay(int n)
函数这个函数是主函数,用于生成外观数列的第
n
个元素。
- 首先,我们初始化结果字符串
ret
为 "1",因为countAndSay(1)
的结果就是 "1"。- 然后,使用一个循环从 2 循环到
n
,在每次循环中,都将当前的ret
字符串传递给dispose
函数进行编码,并将返回的结果重新赋值给ret
。这样,经过n-1
次迭代后,ret
就是我们要找的第n
个外观数列元素。string countAndSay(int n) { string ret("1"); if (n == 1) { return ret; } for (int i = 2; i <= n; i++) { ret = dispose(ret); } return ret; }
4、代码
class Solution {
public:
string dispose(string x)
{
string tmp;//临时存放编码后的字符串
int n = x.size();
if (n == 1)
{
tmp.push_back('1');
tmp.push_back(x[0]);
return tmp;
}
//双指针-->完成行程长度编码
int left = 0, right = 1;
while (right < x.size())
{
while (right < x.size() && x[right] == x[left])
{
right++;
}
string ch = to_string(right - left);
tmp += ch + x[left];
left = right;
}
return tmp;
}
string countAndSay(int n) {
string ret("1");
if (n == 1)
{
return ret;
}
for (int i = 2; i <= n; i++)
{
ret = dispose(ret);
}
return ret;
}
};