题目
报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:
1、1
2、11
3、21
4、1211
5、111221
1 被读作 "one 1" ("一个一") , 即 11。
11 被读作 "two 1s" ("两个一"), 即 21。
21 被读作 "one 2", "one 1" ("一个二" , "一个一") , 即 1211。
给定一个正整数 n(1 ≤ n ≤ 30),输出报数序列的第 n 项。
注意:整数顺序将表示为一个字符串。
示例 1:
输入: 1
输出: "1"
示例 2:
输入: 4
输出: "1211"
题目解释
题目给定一个n,要求报出n项的数。而从题目给出的前五项我们可观察出当前项所报的数都是根据前一个项的数确定的,是对前一项所报数的描述。当前项要报的数是:从左到右依次对前一项中连续出现的数的个数和数的值统计的结果。比如:
第一项,默认是1;
第二项,对第一项进行描述,有1个1,即one one ,也就是第二项的结果“11”;
第三项,对第二项描述,有2个1,即two one,也就是第三项的结果“21”;
第四项,对第三项描述,从左到右依次来,首先有1个2,即one two(12),其次是1个1,即one one(11),结合起来就是one two one one,也就是第四项的结果1211。
后面的项依次这样统计。
java代码实现
本人写的代码较为繁琐,读者可根据自己的理解自行编写。
由于每一项的结果都是根据前一项来的,很容易想到递归,但是LeetCode使用递归会使空间消耗过大,所以只有使用循环,其实现原理类似动态规划中自底向上的思想,由前一项推出后一项,并且每次记录当前的值。
public static String sample(int n) {
//定义一个string数组,每一个元素存储对应下标的报数值
String[] saynum = new String[n];
//count用于对某个数计数,统计其次数
int count = 0;
//第一项默认为1
saynum[0] = "1";
//从第二项开始,直到n项
for(int i = 1; i < n; i++) {
//首先获取前一项的报数值
char[] last = saynum[i - 1].toCharArray();
//记录当前需要报的数串
String cur = "";
//每次对count清零
count = 0;
//对前一项从左到右依次统计
for(int j = 0; j < last.length - 1; j++) {
//如果j元素等于了后面一个元素,count加一
if(last[j] == last[j + 1]) {
count++;
}
//如果j元素不等于后面一个元素,则立马记录j位置数的报数结果
//同时,将count清零,继续对后面的数统计
else {
cur = cur + (count + 1) + last[j];
count = 0;
}
}
//由于上面j的循环是到length减1,循环之后最后一次的统计结果没有记录到cur
//count等于0表示末尾元素是单独出现的,不与前一个元素相同,所以它的出现次数是1
if(count == 0)
cur = cur + "1" + last[last.length - 1];
else
cur = cur + (count + 1) + last[last.length - 1];
//将当前项的报数值记录下来
saynum[i] = cur;
}
//返回第n项的报数
return saynum[n - 1];
}