题目:
给定一个正整数 n(1 ≤ n ≤ 30),输出外观数列的第 n 项。
注意:整数序列中的每一项将表示为一个字符串。
「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。前五项如下
第一项是数字 1
描述前一项,这个数是 1 即 “一个 1 ”,记作 11
描述前一项,这个数是 11 即 “两个 1 ” ,记作 21
描述前一项,这个数是 21 即 “一个 2 一个 1 ” ,记作 1211
描述前一项,这个数是 1211 即 “一个 1 一个 2 两个 1 ” ,记作 111221
示例:
题目解析:
方法一:
- 解题思路:
- 本题的难点在于:报数的概念理解,至少我从题意中没有很清晰的理解,但是感觉像是个递推式
- 从4->5分析,将4个每一位拆开看(个数+数字),4=1211 => 1=11,2=12,11=21,所以5=111221
- 所以解题用循环,从1->n可求解出来
public String countAndSay(int n) {
String str = "1";
for (int i = 2; i <= n; i++) {
StringBuilder builder = new StringBuilder();
char pre = str.charAt(0);
int count = 1;
for (int j = 1; j < str.length(); j++) {
char c = str.charAt(j);
if (c == pre) {
count++;
} else {
builder.append(count).append(pre);
pre = c;
count = 1;
}
}
builder.append(count).append(pre);
str = builder.toString();
}
return str;
}
方法二:双指针 递归操作
解题思路
利用递归和StringBuffer来解析,通过StringBuffer可以大幅度明显感知到其的效率,把数组长度加1来
比如 n=6时,那么用递归得到上一层的字符串str=“111221”
我们将start指向下标0,我们从下标1开始遍历,遍历到“2”下标3的时候,sb拼上(3-0)个1即sb.append(3).append(1),将start指针指向下标3,接着重复以上操作,直到到达str的最后一位,sb直接拼上即可。
class Solution {
public String countAndSay(int n) {
// 递归终止条件
if (n == 1) {
return "1";
}
StringBuffer res = new StringBuffer();
// 拿到上一层的字符串
String str = countAndSay(n - 1);
int length = str.length();
// 开始指针为0
int start = 0;
// 注意这从起始条件要和下面长度统一
for (int i = 1; i < length + 1; i++) {
// 字符串最后一位直接拼接
if (i == length) {
res.append(i - start).append(str.charAt(start));
// 直到start位的字符串和i位的字符串不同,拼接并更新start位
} else if (str.charAt(i) != str.charAt(start) ) {
res.append(i - start).append(str.charAt(start));
start = i;
}
}
return res.toString();
}
}
方法三:
class Solution {
public static String countAndSay(int n) {
StringBuilder ans = new StringBuilder();
ans.append("1");
for (int i = 2; i <= n ; i++) {
//遍历前一个字符串
String currentStr = new String(ans);
ans.delete(0,ans.length());
int num = 0;
char currentChar = currentStr.charAt(0);
for (char c : currentStr.toCharArray()) {
if(c == currentChar){
num++;
}
else{
ans.append((char)('0'+num));
ans.append(currentChar);
currentChar = c;
num = 1;
}
}
ans.append((char)('0'+num));
ans.append(currentChar);
}
return ans.toString();
}
}