A magical string S consists of only ‘1’ and ‘2’ and obeys the following rules:
The string S is magical because concatenating the number of contiguous occurrences of characters ‘1’ and ‘2’ generates the string S itself.
The first few elements of string S is the following: S = “1221121221221121122……”
If we group the consecutive ‘1’s and ‘2’s in S, it will be:
1 22 11 2 1 22 1 22 11 2 11 22 ……
and the occurrences of ‘1’s or ‘2’s in each group are:
1 2 2 1 1 2 1 2 2 1 2 2 ……
You can see that the occurrence sequence above is the S itself.
Given an integer N as input, return the number of ‘1’s in the first N number in the magical string S.
Note: N will not exceed 100,000.
Example 1:
Input: 6
Output: 3
Explanation: The first 6 elements of magical string S is “12211” and it contains three 1’s, so return 3.
// 理解了题意之后,发现这样的magical string是需要构造的,因此,首先根据它的性质把这样的字符串构造出来,再进行统计。这样比较清晰直接
// 具体构造过程见代码
class Solution {
public:
int magicalString(int n) {
if (n == 0) return 0;
// 只有1和2,用vector表示比string方便。
//构造时一次性可能增加两个元素,索性就把vector稍微开大点
vector<int> res(n + 5, 0);
// 先给定三个初值,再进行构造比较方便
//(原本想只给定一个初值就进行构造,但代码写起来总觉得怪怪的,索性直接给三个吧)
res[0] = 1;
res[1] = 2;
res[2] = 2;
// 两个指针,ir指向准备当前已构造好的末尾位置,ig指向的数字帮助我们进行构造,ig<=ir
int ir = 2, ig = 2;
while (ir < n) {
// 从magical string的性质发现,每次构造要么能直接构造两个重复的数,要么只能构造一个
// 且新构造的数总是和前面的数不同
res[ir+1] = (res[ir] == 1) ? 2 : 1;
if (res[ig] == 2) {
res[ir+2] = res[ir+1];
ir += 2;
} else {
ir += 1;
}
++ig;
}
// 最后进行1个数的统计,这里用了for_each和count_if,还有lambda表达式
// 最近正好在补充相关知识,拿出来练习一下
int cnt = 0;
//for_each(res.begin(), res.begin()+n, [&cnt](int x) {if (x == 1) ++cnt;});
cnt = count_if(res.begin(), res.begin()+n, [](int x) {return (x == 1);});
return cnt;
}
};