481. 神奇字符串
神奇字符串 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:
输入:n = 6
输出:3
解释:神奇字符串 s 的前 6 个元素是 “122112
”,它包含三个 1,因此返回 3 。
示例 2:
输入:n = 1 输出:1
提示:
1 <= n <= 105
神奇字符串:
122 112 122 122 112 112 221 212 212...
前20列是题目给的
规律:
字符串str与其子串p, 字符串str可以根据字符串p来进行扩展(扩展的规则是: 新加入的部分是由当前字符串str的末尾数字反转而来(即 1 => 2, 2 => 1)),该数字的重复次数从字符串p中取得。一开始较短和较长字符串都置为"122", i 指向字符串p的末尾。
字符串p可以看成是字符串str的压缩形式(只存了未来新加入的数字应该出现的次数)。
字符串p: 每次从字符串str中index = i 的地方复制一个数字插入到字符串p的末尾。这个数字就是后面字符串str中新加入的数字应该出现的次数,且这个新加入的数字 = 当前字符串str的末尾数字反转而来(即 1 => 2, 2 => 1) 。
算法步骤:
构造两个长度在增长的字符串, 使用两个指针分别指向这两个字符串末尾, i 指向较短的字符串末尾接下来在字符串str末尾加字符来扩展它
一开始较短和较长字符串都置为"122", i 指向较短的字符串末尾
对字符串str 进行扩展,直到 str.size() >= n 位置。
作者:极客学长Bravo
链接:https://leetcode.cn/problems/magical-string/solutions/1037835/geekplayers-leetcode-ac-qing-xi-yi-dong-2pdyf/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。注: 图中每两行(第1行是字符串str, 第2行是字符串p, p是str的子串)是字符串str的1次扩展
class Solution:
def magicalString(self, n: int) -> int:
i = 2#指针指向第3个位置
index = 1 #用来决定数列是增加1,还是增加2.默认1增加1,-1增加2
lst = [1, 2, 2]#构建一个列表,存放数字
num_1 = 1#用来记录数列中1的个数
num_2 = 2#用来记录数列中2的个数
num_sum = 3#用来记录数列中数字1和2的总长度
while num_sum < n:
if index == 1:
lst += lst[i] * [1]#例如:2*【1】 = 【1,1】
num_1 += lst[i]
num_sum += lst[i]
if num_sum > n:#num_sum最多 == n + 1
num_1 -= 1#由于增加的项数不固定,有时候当num_sum = n-1的时候,再进行一次循环后可能变为n+1这时要减去1
elif index == -1:
lst += lst[i] * [2]
num_2 += lst[i]
num_sum += lst[i]
if num_sum > n:
num_2 -= 1
index *= -1
i += 1
return num_1