0038. Count and Say (E)
Count and Say (E)
题目
The count-and-say sequence is the sequence of integers with the first five terms as following:
1. 1
2. 11
3. 21
4. 1211
5. 111221
1
is read off as "one 1"
or 11
.
11
is read off as "two 1s"
or 21
.
21
is read off as "one 2
, then one 1"
or 1211
.
Given an integer n where 1 ≤ n ≤ 30, generate the nth term of the count-and-say sequence.
Note: Each term of the sequence of integers will be represented as a string.
题意
定义一组数字序列为:每一个数字序列都是对上一个数字序列的“描述”,如第一个序列为“1”,第二个序列为“11”(描述第一个序列中有1个1),第三个序列为“21”(描述第二个序列中有2个1),第四个序列为“1211”(描述第三个序列中有1个2、1个1)……要求返回第n个序列。
思路
创建一个next(String s)方法来根据上一个序列计算下一个序列。为了避免多次重复的计算,用一个List来保存各个序列。
代码实现
Java
class Solution {
// 保存计算过的序列,避免重复运算
private List<String> list = new ArrayList<>();
public String countAndSay(int n) {
// 首先找是否已经计算过对应的值
if (n <= list.size()) {
return list.get(n - 1);
}
// 尚未计算对应值,则从已有的最后一个序列开始计算到指定序列
while (list.size() < n) {
String s = list.size() == 0 ? null : list.get(list.size() - 1); // 注意没有一个已计算的情况
list.add(next(s));
}
return list.get(n - 1);
}
private String next(String s) {
// 特殊情况,计算第一个序列
if (s == null) {
return "1";
}
StringBuilder sb = new StringBuilder();
int count = 1;
for (int i = 0; i < s.length(); i++) {
if (i > 0) {
if (s.charAt(i) == s.charAt(i - 1)) {
count++;
} else {
sb.append(count);
sb.append(s.charAt(i - 1));
count = 1;
}
}
}
sb.append(count);
sb.append(s.charAt(s.length() - 1));
return sb.toString();
}
}
JavaScript
/**
* @param {number} n
* @return {string}
*/
var countAndSay = function (n) {
let count = 1
let s = '1'
while (count !== n) {
let times = 1
let t = ''
for (let i = 1; i < s.length; i++) {
if (s[i] === s[i - 1]) {
times++
} else {
t += times + '' + s[i - 1]
times = 1
}
}
t += times + '' + s[s.length - 1]
s = t
count++
}
return s
}