题目描述
The count-and-say sequence is the sequence of integers beginning as follows:
1, 11, 21, 1211, 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, generate the nth sequence.
Note: The sequence of integers will be represented as a string.
题目详解
个人认为这是一道非常神奇的题目,因为刚开始做的时候,我竟然完全没有理解题目的意思。刚开始我以为是要给一个字符串,eg. 111221,然后输出其个数的描述,如”three 1, two 2, one 1”或是”312211”这种形式就可以了。后来提交之后说我结果不对,搜了一下才知道原来相当于一个序列的描述。
输入整数n,输入序列中的第n个字符串,字符串的规则如下:
- n=1, s=”1”
- n=2, s=”11” (这里的”11”就是对n=1时字符串的描述)
- n=3, s=”21” (对n=2时字符串的描述)
- n=4, s= “1211” (对n=3时字符串的描述)
根据上述规则,以此类推,得到第n个字符串的描述。
解决思路
题目的解决思路是需要保存前一个字符串,在对前一个字符串进行统计得到当前字符串的一个循环操作。
字符串统计即通过对字符串进行遍历,若后一个字符串与前一个字符串相等,则对字符串的计数count+1,若不相等则重新设置前一个字符串,并将计数count置为0.
另外不要忘记了对输入值的一个判断,若n<0则返回空字符串。废话不多说,直接上代码。
class Solution {
public:
string countAndSay(int n) {
if (n < 0)
return "";
string res = "1";
int i = 1;
while (i < n)
{
string next;
int j = 0;
while (j < res.size())
{
char priv = res[j];
int count = 0;
while (j < res.size() && res[j] == priv)
{
count++;
j++;
}
next.append(1, count + ‘0‘);
next.append(1, priv);
}
res = next;
i++;
}
return res;
}
};
上面这段代码的运行时间为3ms,已经算是比较高效的了,在这之前我实现了一个比较慢的算法(18ms),这里也贴出来,供比较,从代码可以看出上一个代码的比较比较简洁,且字符串的增加直接使用了string类型的append函数,而下面的代码比较部分比较繁琐,进行了多次if判断,在得到结果时使用了stringstream类将数字转为字符串,这些都是造成该算法较慢的原因。
class Solution {
public:
string countAndSay(int n) {
if (n < 0)
return "";
int i = 1;
string last = "1";
for (i = 2; i != n + 1; ++i)
{
string builder;
string::iterator it = last.begin();
int count(0);
for (it; it != last.end(); ++it)
{
count++;
if ( (it+1)!=last.end() && *it != *(it+1))
{
stringstream ss;
ss << count << *it;
builder += ss.str();
count = 0;
}
else if (it+1 == last.end())
{
stringstream ss;
ss << count << *it;
builder += ss.str();
}
}
last = builder;
}
return last;
}
};