题目链接:Count and Say报数
一开始试图找规律,直接写了个简单粗暴的代码,跑起来好像没发现规律。
试着提交居然过了,但是速度比较慢,就改进了下代码。
按题意来的简单粗暴的代码(40ms)如下:
public String countAndSay(int n) {
List<Integer> arr = new ArrayList<Integer>();
List<Integer> res = new ArrayList<Integer>();
arr.add(1); // 初始化数列
for (int i = 2; i <= n; i++) {
int count = 0, pre = -1; // 用pre存储数列中arr(k)的前一个数
for (int k = 0; k < arr.size(); k++) {
// 判断前一个数是否与当前数相等,是则count+1
// 否则将count与pre存入res,重置count,pre
if (((Integer)arr.get(k)) != pre) {
if (count > 0) {
res.add(count);
res.add(pre);
}
count = 1;
pre = arr.get(k);
} else count++;
}
res.add(count);
res.add(pre);
arr.clear(); // 将arr清空
arr.addAll(res); // 将res数列复制到arr中
res.clear(); // 将res清空
}
StringBuilder ans = new StringBuilder();
// 遍历数列已返回结果
for (Integer a : arr) ans.append(a);
return ans.toString();
}
之后做了一些改进(5ms),这样的改进,测试数据组数越多,效果越明显
public class CountAndSay {
/*改进:
* 1.第一次提交后发现n貌似不是特别大
* n范围好像是1--57
* 所以可以使用一个List<StringBuilder>来
* 存我们求n时计算的n-1,n-2,....,3,2,1避免了一些重复计算
* 2.直接使用StringBuilder,
* 比List<Integer>转String减少了个循环,
* 3.至于为何不直接用String,
* 这样StringBuilder到toString都免了,
* 请自行百度StringBuilder与String顺带个StringBuffer
* */
private static List<StringBuilder> list = new ArrayList<StringBuilder>(60);
static {
list.add(new StringBuilder("1"));
}
public String countAndSay(int n) {
if (list.size() > n - 1) {
if (n - 1 < 0) return null;
return ((StringBuilder)list.get(n - 1)).toString();
} else {
StringBuilder arr = (StringBuilder)list.get(list.size() - 1);
StringBuilder res = new StringBuilder();
for (int i = list.size(); i < n; i++) {
int count = 0;
char pre = 0;
for (int k = 0; k < arr.length(); k++) {
if (arr.charAt(k) != pre) {
if (count > 0) res.append(count).append(pre);
count = 1;
pre = arr.charAt(k);
} else count++;
}
res.append(count).append(pre);
arr = res;
res = new StringBuilder();
list.add(arr);
}
return arr.toString();
}
}
}