38. 报数
难度:简单
这道题算法不难,难的是读懂题😂,下面会说一下这道题到底要干嘛
1. 题目描述
报数序列是一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:
1. 1
2. 11
3. 21
4. 1211
5. 111221
1 被读作 "one 1" ("一个一") , 即 11。
11 被读作 "two 1s" ("两个一"), 即 21。
21 被读作 "one 2", "one 1" ("一个二" , "一个一") , 即 1211。
给定一个正整数 ,输出报数序列的第
项。
注意:整数顺序将表示为一个字符串。
示例 1:
输入: 1
输出: "1"
示例 2:
输入: 4
输出: "1211"
2. 解题思路
读完题一脸懵逼,在读一遍还是一脸懵逼,读了几遍才知道要干嘛。
这道题其实是给定一个正整数 ,找到这项对应的报数序列。
- 怎么找?答案是根据这个
的前一项进行报数
- 怎么报数?从左往右,遇到相同的数字看成一个整体连在一起读
- 比如第
项是
1211,拆分后可以看做1``2``11,读出来就是,1个1,1个2,2个1,将这几个数字从左到右拼在一起就是111221 - 比如第
项是
111221,拆分后可以看做111``22``1,读出来就是,3个1,2个2,1个1,将这几个数字从左到右拼在一起就是312211
- 比如第
- 要算出当前项的报数序列,就要先算出前一项的报数序列,明显要用递归方法,而递归的约束条件就是第
项这个初始条件
1,初始条件不同后续的序列就不同
Java实现:
public String countAndSay(int n) {
if (n == 1) {
return "1";
} else {
String before = countAndSay(n - 1);
StringBuilder sb = new StringBuilder();
// 数字分组的依据,记录当前对那个数字进行分组,默认取第一个
char c = before.charAt(0);
// 因为默认取第一个数字作为分组依据,所以当前组的数字个数已经为1了
int count = 1;
// 从第2个数字开始遍历(如果字符串长度 > 1)
for (int i = 1; i < before.length(); i++) {
char tmp = before.charAt(i);
if (c == tmp) {
// 如果当前遍历数字和分组数字一致,则继续遍历,该组个数 +1
count++;
} else {
// 如果当前遍历数字和分组数字不一致,将分组数字拼接到结果中
// 重新开始一个分组,注意这里拼接的已经是上一个分组数据了
// 所以字符串最后一个分组是不会在这里拼接到最终返回结果中的,只是保存了
sb.append(count).append(Character.getNumericValue(c));
c = tmp;
count = 1;
}
}
// 如果上一个只有一位,根本不会进入for循环,我们只记录了代表分组的数字,和个数,还没拼接到结果中
// 遍历到for循环的最后一位数字时,结果只是保存在了 c、count两个变量中,这里拼接上
sb.append(count).append(Character.getNumericValue(c));
return sb.toString();
}
}
运行结果如下: