问题描述
问题分析
分析题目,是一个简单模拟的题目,主要难度在于理解题意。
题意:
- 第一个数是1;
- 由于上一个数“1”是1个1,所以第二个数是11;
- 由于上一个数“11”是2个1,所以第二个数是21;
- 由于上一个数“21”是先1个2,再1个1,所以第二个数是1211;
- 依次类推
简单模拟的方法就是读数的方法,我就简述一下思路:
- 首先定义外循环和内循环。外循环依次定义results[30]这个数组的每一个元素,内循环遍历上一个元素的每一个字符。
- 外循环不必说,记录内循环的当前元素,和这个元素的个数
- 内循环的循环体思路是:依次比较该元素与外循环记录的当前元素,如果相同则长度+1,如果不同则结算(将当前元素和长度加到结果数组的对应元素中去)并且更新当前数字和长度。
- 需要注意的地方是需要注意最后一个字符。
解法:简单模拟
- 时间复杂度:O( nm ),其中n表示数组的长度,m表示数组中数字的平均长度。
Java代码
class Solution {
public String countAndSay(int n) {
int index, number, length, stringLength;
String[] results;
results = new String[31];
results[1] = "1";
for (int i = 2; i < 31; i++) {
//初始化
results[i] = "";
//当前数字
number = results[i - 1].charAt(0) - '0';
//当前数字的个数
length = 0;
//上一个字符串的长度
stringLength = results[i - 1].length();
//对上一个字符串的字符依次判定
for (index = 0; index < stringLength; index++) {
if ((results[i - 1].charAt(index) - '0') == number){
//个数更新
length++;
}else {
//结算,数字和个数更新
results[i] += String.valueOf(length);
results[i] += String.valueOf(number);
//更新
number = results[i - 1].charAt(index) - '0';
length = 1;
}
if (index == stringLength - 1){
results[i] += String.valueOf(length);
results[i] += String.valueOf(number);
}
}
}
return results[n];
}
}
结果分析
以上代码的执行结果:
执行时间 | 内存消耗 |
---|---|
299 ms | 55.1 MB |
可能是new了太多String和对String进行了太多拼接操作,所以导致花费的时间很高。可以使用StringBuffer优化一下。