38. Count and Say - LeedCode

38. Count and Say

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, generate the nth term of the count-and-say sequence.

Note: Each term of the sequence of integers will be represented as a string.

Example 1:

Input: 1
Output: “1”

Example 2:

Input: 4
Output: “1211”

Solution1:

用栈实现, 从低递推, 扫描一遍, 不同的数字将栈清空并加入到字符串中; 注意最后若非空栈也需要清空一次.

class Solution {
public:
string countAndSay(int n) {
if (n == 0) return "";
string ans = "1"; n--;
stack<char> stk;
while (n--) {
string temp;
int i = 0;
for (int i = 0; i < ans.length(); i++) {
if (!stk.empty() && stk.top() != ans[i]) {
temp += stk.size() + '0';
temp += stk.top();
while (!stk.empty()) stk.pop();
}
stk.push(ans[i]);
}
if (!stk.empty()) {
temp += stk.size() + '0';
temp += stk.top();
while (!stk.empty()) stk.pop();
}
ans = temp;
}
return ans;
}

};

Solution2:

在for循环中, 循环体中改变i是可行的; for语句执行的顺序是

for (进入循环之前的定义和声明等; 循环体执行条件; 循环体执行后的变量改变) {
// 循环体
}

因此, 在内部改变i, 可以使得只扫描一次.

// Time:O(n), Space:O(n)
// 指针的版本, for循环中用while跳跃
class Solution {
public:
string countAndSay(int n) {
if (n == 0) return "";
string res = "1";
while (--n) {
string cur = "";
for (int i = 0; i < res.size(); i++) {
int cnt = 1;
while ((i+1 < res.size()) && res[i] == res[i+1]) {
cnt++;
i++;
}
cur += to_string(cnt) + res[i];
}
res = cur;
}
return res;
}
};