题目:
给定一个正整数 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"
解题思路:
已知外观数列第一项为“1”,求解外观数列的第n项。
新建String对象“1”,用两个循环来模拟第n项外观数列的构建过程:loop1的每次循环代表1次外观数列的构建过程,一共有n次循环;loop2代表遍历上一项外观数列的字符串的过程,从而生成新的外观数列,循环次数为上一项字符串的长度。
新建StringBuilder对象,其中loop2(索引为j = 0)的过程为:
1. 记录下当前字符,并设置计数器为1,j++;
2. 向后比较,不超过字符串长度的情况下,当字符与记录下的字符相等,计数器加1,j++,直到不符合判断;
3.为了下次循环开始记录当前字符,索引j向前移动,并把计数器和当前字符append到StringBuilder对象后。
loop2循环结束后,把StringBuilder对象赋值给String对象。
public String countAndSay(int n) {
String lastStr = "1";
loop1:for (int i = 2; i <= n; i++) {
StringBuilder currentStr = new StringBuilder();
loop2:for (int j = 0; j < lastStr.length(); j++) {
char temp = lastStr.charAt(j);
int count = 1;
j++;
while (j < lastStr.length() && lastStr.charAt(j) == temp) {
j++;
count++;
}
if (j < lastStr.length()) j--;
currentStr.append(count).append(temp);
}
lastStr = currentStr.toString();
}
return lastStr;
}