神奇字符串【LC481】
神奇字符串
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
的数目。
这是什么智力题吗?参考三叶姐
-
思路:根据规律构造神奇字符串,统计1的个数后返回
-
规律
-
神奇字符串
s
称为“原串”,对s
进行连续段划分所得的串叫“划分串”,对划分串进行计数的串叫“计数串”。 -
划分串的长度只能是1或者2
-
计数串总是短于原串,因此使用变量i记录当前构造到原串的位置,使用变量j来记录计数串对应的位置
-
可以分四种情况构造神奇字符串
-
当原串当前字符为1,计数串当前字符为1
那么原串只能添加字符’2’,原串指针后移一位
-
当原串当前字符为1,计数串当前字符为2
那么原串只能添加字符’12’,原串指针后移两位
-
当原串当前字符为2,计数串当前字符为1
那么原串只能添加字符’1’,原串指针后移一位
-
当原串当前字符为2,计数串当前字符为2
那么原串只能添加字符’21’,原串指针后移两位
-
-
-
代码
class Solution { public int magicalString(int n) { char[] chars = new char[100001]; chars[0] = '0';// 哨兵 chars[1] = '1'; int count = 1; if (n < 4){ return count; } int i = 1, j = 1; while (i < n){ if (chars[i] == '1'){ if (chars[j] == '1'){ chars[++i] = '2'; }else { chars[++i] = '1'; chars[++i] = '2';// 多构造一位不影响结果 count++; } }else { if (chars[j] == '1'){ chars[++i] = '1'; count++; }else { chars[++i] = '2'; if (i + 1 <= n){// 多构造一位影响结果 chars[++i] = '1'; count++; } } } j++; } return count; } }
-
复杂度
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( n ) O(n) O(n)