题目描述
【leetcode】38. 外观数列(Count and Say)
「外观数列」是一个整数序列,从数字 1 开始,序列中的每一项都是对前一项的描述。前五项如下:
1. 1
2. 11
3. 21
4. 1211
5. 111221
1 被读作 “one 1” (“一个一”) , 即 11。
11 被读作 “two 1s” (“两个一”), 即 21。
21 被读作 “one 2”, “one 1” (“一个二” , “一个一”) , 即 1211。
给定一个正整数 n(1 ≤ n ≤ 30),输出外观数列的第 n 项。
注意:整数序列中的每一项将表示为一个字符串。
第一次解答
思路:
每次都从1开始便利到指定的n值
中间变量全用字符串表示
从左到右便利每个字符
last 记录上一个字符,与当前字符判断,如果相同,则计数count++
若不相同则输出,并更改last
注意:
本解法假定了同一个数字只出现9次以下
否则,例如有10个1,应该表示为101,本题表示不了
不过换一个方面想,会出现超过两位数长度的相同数字吗?
test case:
1
2
29
30
using namespace std;
class Solution {
public:
string countAndSay(int n) {
string value_str = "1";
string count_say = "";
if(1==n)
return string("1");
while(--n > 0){
count_say.clear();
char last_char = value_str[0];
char count = 1;
for(int i=1; i<value_str.size(); ++i){
if(last_char == value_str[i]){
++count;
}
else{
count_say.append(1, char(count+'0'));
count_say.append(1, last_char);
count = 1;
last_char = value_str[i];
}
}
count_say.append(1, char(count+'0'));
count_say.append(1, last_char);
value_str = count_say;
}
return count_say;
}
};
结果:
第二次解答
看到有人用递归来写,我也来试试:
思路:
用递归的方法实现解答一的思路,countAndSay(n)的输出等于
对countAndSay(n-1)的输出进行报数。
using namespace std;
class Solution {
public:
string countAndSay(int n) {
if(1==n)
return string("1");
string curr_countAndSay = countAndSay(n-1);//递归
string count_say = "";
char last_char = curr_countAndSay[0];
char count = 1;
for(int i=1; i<curr_countAndSay.size(); ++i){
if(last_char == curr_countAndSay[i]){
++count;
}
else{
count_say.append(1, count+'0');//这里假定count<=9
count_say.append(1, last_char);
count = 1;
last_char = curr_countAndSay[i];
}
}
count_say.append(1, count+'0');//这里假定count<=9
count_say.append(1, last_char);
return count_say;
}
};
结果:
结果分析:这里执行用时比解法1快,内存消耗比解法1大,应该是因为递归减少了count_say.clear(),的操作,并且减少了由于count_say.append()时,count预分配内存不足产生的内存重申请和整体拷贝的操作。