给定一个正整数 n
,输出外观数列的第 n
项。
「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。
你可以将其视作是由递归公式定义的数字字符串序列:
countAndSay(1) = "1"
countAndSay(n)
是对countAndSay(n-1)
的描述,然后转换成另一个数字字符串。
前五项如下:
1. 1
2. 11
3. 21
4. 1211
5. 111221
第一项是数字 1
描述前一项,这个数是 1 即 “ 一 个 1 ”,记作 "11"
描述前一项,这个数是 11 即 “ 二 个 1 ” ,记作 "21"
描述前一项,这个数是 21 即 “ 一 个 2 + 一 个 1 ” ,记作 "1211"
描述前一项,这个数是 1211 即 “ 一 个 1 + 一 个 2 + 二 个 1 ” ,记作 "111221"
要 描述 一个数字字符串,首先要将字符串分割为 最小 数量的组,每个组都由连续的最多 相同字符 组成。然后对于每个组,先描述字符的数量,然后描述字符,形成一个描述组。要将描述转换为数字字符串,先将每组中的字符数量用数字替换,再将所有描述组连接起来。
例如,数字字符串 "3322251"
的描述如下图:
示例 1:
输入:n = 1
输出:"1"
解释:这是一个基本样例。
示例 2:
输入:n = 4
输出:"1211"
解释:
countAndSay(1) = "1"
countAndSay(2) = 读 "1" = 一 个 1 = "11"
countAndSay(3) = 读 "11" = 二 个 1 = "21"
countAndSay(4) = 读 "21" = 一 个 2 + 一 个 1 = "12" + "11" = "1211"
提示:
1 <= n <= 30
按照题意计算就好了,使用两个for循环,第2个循环不断的统计字符串中字符的个数,然后存储到一个StringBuilder中,然后这个StringBuilder会作为下一个统计开始的字符串……,重复上面的操作
StringBuilder:可以修改的字符串
互相转换:
StringBuilder——>String : toString()
String ——> StringBuilder : new StringBuilder (s)
class Solution {
public String countAndSay(int n) {
// 初始化当前项为 "1"
StringBuilder res = new StringBuilder("1");
StringBuilder prev; // 用于存储前一项序列
int count; // 记录字符出现次数
char say; // 记录当前正在统计的字符
// 从第二项开始构建序列,直到第 n 项
for (int i = 1; i < n; i++) {
// 将当前项赋值给 prev
prev = res;
// 创建一个新的 StringBuilder 用于构建下一项序列
res = new StringBuilder();
// 初始化字符出现次数为 1,因为每个字符至少出现一次
count = 1;
// 获取前一项序列的第一个字符作为当前正在统计的字符
say = prev.charAt(0);
// 遍历前一项序列,从第二个字符开始
for (int j = 1, len = prev.length(); j < len; j++) {
// 如果当前字符与正在统计的字符不同,表示遇到了新的字符
if (prev.charAt(j) != say) {
// 将之前统计的字符及其出现次数加入到 res 中
res.append(count).append(say);
// 将出现次数重新置为 1,因为遇到了新的字符
count = 1;
// 更新正在统计的字符为新的字符
say = prev.charAt(j);
} else {
// 如果当前字符与正在统计的字符相同,则增加出现次数
count++;
}
}
// 将最后一个字符及其出现次数加入到 res 中
res.append(count).append(say);
}
// 返回第 n 项的描述
return res.toString();
}
}
-
StringBuilder res = new StringBuilder("1");
:首先创建一个 StringBuilder 对象 res,并将其初始化为 “1”。这个 StringBuilder 用来存储当前正在构建的序列。 -
StringBuilder prev;
:声明一个 StringBuilder 对象 prev,用来存储前一项的序列。 -
int count;
:用来记录字符出现的次数。 -
char say;
:用来记录当前正在统计的字符。 -
for (int i = 1; i < n; i++) {
:外层循环,从第二项开始构建序列,直到第 n 项。 -
prev = res;
:将当前构建好的序列 res 赋值给 prev,以备后用。 -
res = new StringBuilder();
:创建一个新的 StringBuilder 对象 res,用于构建下一项的序列。 -
count = 1;
:初始化 count 为 1,因为每个字符至少出现一次。 -
say = prev.charAt(0);
:获取前一项序列的第一个字符,作为当前正在统计的字符。 -
for (int j = 1, len = prev.length(); j < len; j++) {
:内层循环,遍历前一项的序列,从第二个字符开始。 -
if (prev.charAt(j) != say) {
:如果当前字符与正在统计的字符不相同,表示遇到了新的字符。 -
res.append(count).append(say);
:将之前统计的字符及其出现次数加入到 res 中。 -
count = 1;
:将 count 重新置为 1,因为遇到了新的字符。 -
say = prev.charAt(j);
:将正在统计的字符更新为新的字符。 -
else { count++; }
:如果当前字符与正在统计的字符相同,则增加 count。 -
res.append(count).append(say);
:将最后一个字符及其出现次数加入到 res 中。 -
return res.toString();
:将 StringBuilder 对象 res 转换为字符串并返回,即为第 n 项的描述。
这样,每次迭代都会根据前一项的描述构建出下一项的描述,直到得到第 n 项的描述为止。
标签:count,字符,38,数列,StringBuilder,say,LeeCode,res,prev From: https://blog.csdn.net/kdzandlbj/article/details/136991989