每一个数字 n 对应的string都是完全由数字 n-1对应的string决定的,也就是1->2,2->3,3->4…
依次递推的。
递推的规则可以这么描述:
假设数字 n-1 对应的字符串 s已知,那么对s中的字符,从左到右-可以划分为多个区间(每个区间的元素都是一样的),比如 "11221"可以分为三部分 “111221”,每部分的特点可以用两个变量描述:num记录该部分的数字是多少,count记录数字的个数是多少。
那么,该部分映射到数字 n 对应的字符串就是 “count”+“num”。
至于处理方式,可以处理字符串或者数组,也可以转为数字处理,但是数字会面临溢出的问题。
用数组处理的好处是可以直接处理int型数字,最后转化为string返回即可,而且并不需要n个数组分别保存从1到n的结果值,我们可以使用滚动数组,因为计算n只需要知道n-1就行,两个数组即可。
class Solution {
public:
string countAndSay(int n) {
string res("");
vector<vector<int>> a{{1}, {}};//第一项一个1,第二项先初始化为0
int cur = 0, pre = 1-cur;
for(int i = 2; i <= n; ++i){
cur = i%2;
pre = 1-cur;
for(int j = 0; j < a[cur].size();){
int num = a[cur][j];
int count = 1;
while(j+1 < a[cur].size() && a[cur][j+1] == num){
++count;
++j;
}
a[pre].push_back(count);
a[pre].push_back(num);
++j;
}
a[cur].clear();
}
for(const auto &c : a[(n-1)%2]) res += to_string(c);
return res;
}
};
不过写完感觉不用数组,直接处理字符串好像也差不多:
class Solution {
public:
string countAndSay(int n) {
string s1("1"), s2("");//第一项一个1
for(int i = 2; i <= n; ++i){
for(int j = 0; j < s1.size();){
char num = s1[j];
int count = 1;
while(j+1 < s1.size() && s1[j+1] == num){
++count;
++j;
}
s2 += to_string(count);
s2 += num;
++j;
}
s1.clear();
s1 = s2;
s2.clear();
}
return s1;
}
};