二、字符串(35)481. 神奇字符串

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值