题目大意
「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。前五项如下:
-
1
-
11
-
21
-
1211
-
111221
1 被读作 “one 1” (“一个一”) , 即 11。
11 被读作 “two 1s” (“两个一”), 即 21。
21 被读作 “one 2”, “one 1” (“一个二” , “一个一”) , 即 1211。
给定一个正整数 n(1 ≤ n ≤ 30),输出外观数列的第 n 项。
注意:整数序列中的每一项将表示为一个字符串。
解题思路
由于第n个序列需要用到第n-1个序列的结果,因此很容易想到采用递归的方式来求解。
当n=1时,显而易见,结果为“1”;
当n>1时,需要第n-1的结果字符串;
因此,整个大过程可写成如下形式。其中countAndSay()表示返回第n个序列的字符串结果。当n!=1时,需要用到第n-1个系列的字符串结果,因此首先调用countAndSay(n-1)返回第n-1个序列的结果,然后通过getCurCount()函数计算第n个序列的字符串结果。
string countAndSay(int n) {
if (n == 1)
return "1";
return getCurCount(countAndSay(n - 1));
}
getCurCount()函数的作用是计算传入的字符串,根据该字符串返回下一个字符串。从第二个位置开始遍历当前字符串,如果跟前一个字符串相同,则统计次数(count初始化是1),若不相同,则结算当前位置的前一个位置字符。由于遍历完成后,最后一个字符及其之前的相同的部分没有被结算,因此最后加上该部分即可。
string getCurCount(string str){
int count = 1;
string ans = "";
for (int i= 1;i < str.size(); ++i){
//如果当前字符与前一个字符相同,则继续统计数量
if (str[i] == str[i - 1])
++count;
else{
//将该位置的前一个字符以及出现的次数进行结算,并重新初始化count
ans += to_string(count) + str[i - 1];
count = 1;
}
}
//由于每次我们只结算i位置的前一个位置的字符以及次数
//因此当循环遍历后,并未计算最后一个字符及出现次数,所以这里需要单独补充
ans += to_string(count) + str[str.size() - 1];
return ans;
}