题目大意
神奇字符串
神奇字符串 s 仅由 ‘1
’ 和 ‘2
’ 组成,并需要遵守下面的规则:
- 神奇字符串 s 的神奇之处在于,串联字符串中 ‘
1
’ 和 ‘2
’ 的连续出现次数可以生成该字符串。 - s 的前几个元素是 s = “
1221121221221121122……
” 。如果将 s 中连续的若干 1 和 2 进行分组,可以得到 “1 22 11 2 1 22 1 22 11 2 11 22 ......
” 。每组中 1 或者 2 的出现次数分别是 “1 2 2 1 1 2 1 2 2 1 2 2 ......
” 。上面的出现次数正是 s 自身。
给你一个整数 n ,返回在神奇字符串 s 的前 n 个数字中 1 的数目。
输入:n = 6
输出:3
解释:神奇字符串 s 的前 6 个元素是 “122112”,它包含三个 1,因此返回 3 。
思路分析
这个问题不光需要我们返回前 n 个数字中 1 的数目,还需要我们对S进行构造(不构造也可以,不太好想)。
我们可以直接指定s的前3个元素是122
。我们根据题意知道1
和2
是交叉出现的。而当前数字出现的次数取决于指针i所指向的元素。
如上图所示,我们已知s='122'
,指针i指2,我们打算构造122112122
,红色是根据根据指针i构造的元素,灰色是未被构造的。
因为1
和2
是交叉出现的,所以说下一个是1
,该值出现的次数是指针i所指向的元素2,接着i指向下一个元素,循环这个过程。
代码
class Solution {
public int magicalString(int n) {
char[] s = new char[n + 2];
// 定义S的初始值
s[0] = 1; s[1] = s[2] = 2;
char c = 2;
for(int i=2,j=3; j<n;i++){
// 异或 1^=3=2 2^=3=1
// 这样可以在1和2之间反复
c ^= 3;
s[j++] = c;
//如果指针i指向的元素是2,那么额外加一个
if(s[i]==2) s[j++]=c;
}
int ans = 0;
for(int i=0; i<n; i++) if(s[i] == 1) ans+=1;
return ans;
}
}