给定一个正整数 n ,输出外观数列的第 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"
要 描述 一个数字字符串,首先要将字符串分割为 最小 数量的组,每个组都由连续的最多 相同字符 组成。
然后对于每个组,先描述字符的数量,然后描述字符,形成一个描述组。再将所有描述组连接起来。
解析:
两种方式,循环和递归
可以用一个变量记录一个描述组的字符,同时记录描述组字符的个数;
也可以直接记录一个描述组的开始索引,以及最后一个不相同的位置;
然后得到描述字符的个数,以及描述字符。最后注意边界条件,考虑n=1的情况,把边界加入;
package com.vincent.leetcode;
public class leetcode38 {
public static void main(String[] args) {
// TODO Auto-generated method stub
int n=8;
System.out.println(countAndSay1(n));
}
//循环
public static String countAndSay(int n) {
if(n==1){
return "1";
}
int i=1;
StringBuilder result = new StringBuilder();
StringBuilder preResult = new StringBuilder();
preResult.append("1");
for(;i<n;i++){
Character ch;
int count=1;
int j=0;
for(;j<preResult.length()-1;j++){
ch = preResult.charAt(j);
if(preResult.charAt(j+1)==preResult.charAt(j)){//如果j位置的字符与j+1位置的字符相同,则count加1
count++;
}else{//如果j和j+1位置的字符不同,则说明可以把该字符的个数和该字符加入结果了,然后count重置为1,开始统计下个字符连续出现的数量
result.append(count);
result.append(ch);
count=1;
}
}
if(j<preResult.length()){//加入最后一个字符及它的个数
result.append(count);
result.append(preResult.charAt(preResult.length()-1));
}
preResult.delete(0, preResult.length());//清理上一个结果
preResult.append(result.toString());
result.delete(0, result.length());
}
return preResult.toString();
}
//循环
public static String countAndSay1(int n) {
StringBuilder preResult = new StringBuilder();
//记录当前行的字符串,即n为i时对应的字符串
StringBuilder result = new StringBuilder();
preResult.append(1);
for(int i=1;i<n;i++){
//记录每个数字的开始索引
int start = 0;
for(int j=1;j<preResult.length();j++){
//当数字发生改变时执行
if(preResult.charAt(j)!=preResult.charAt(start)){
result.append(j-start).append(preResult.charAt(start));
start = j;
}
}
//字符串最后一个字符,可以考虑i=1时;
result.append(preResult.length()-start).append(preResult.charAt(start));
preResult.delete(0, preResult.length());
preResult.append(result);
result.delete(0, result.length());
}
return preResult.toString();
}
//递归
public static String countAndSay2(int n) {
//递归终止条件
if(n==1){
return "1";
}
//获取到上一层的字符串
String preResult = countAndSay2(n-1);
StringBuilder result = new StringBuilder();
//记录每个数字的开始索引
int start = 0;
for(int i=1;i<preResult.length();i++){
//当数字发生改变时执行
if(preResult.charAt(i)!=preResult.charAt(start)){
result.append(i-start).append(preResult.charAt(start));
start = i;
}
}
//字符串最后一个数字
result.append(preResult.length()-start).append(preResult.charAt(start));
return result.toString();
}
}