持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第32天,点击查看活动详情
题目
神奇字符串 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 <= 10^5
思考
本题难度中等。
首先是读懂题意。神奇字符串 s 仅由 '1' 和 '2' 组成。给你一个整数 n ,返回在神奇字符串 s 的前 n 个数字中 1 的数目。已知神奇字符串的前几位为 1221121221221121122 …
观察神奇字符串1221121221221121122 …,我们定义字符串 str 为122,猜想字符串接下来的字符组成。对于str[2],表示接下来会有两个相同的字符,也表示接下来的字符是1而不是2。因此,我们定义start和end两个指针,str[start]表示字符的数量,str[end]表示下一个字符的组成,若str[end]为1,则下一个字符为2,反之则为字符1。那么,我们可以构造出神奇字符串来。
接着,我们遍历字符串的前 n 个字符,计算其中字符1的数量并返回即可。
解答
方法一:双指针
/**
* @param {number} n
* @return {number}
*/
var magicalString = function(n) {
let str = '122', start = 2, end = 2
while (str.length < n) {
// 数量str[start], 最后一个字符str[end]
if (str[start] === '1') {
if (str[end] === '1') {
str += '2'
} else {
str += '1'
}
end++
} else {
if (str[end] === '1') {
str += '22'
} else {
str += '11'
}
end += 2
}
start++
}
let num = 0
for (let i = 0; i < n; i++) {
if (str[i] === '1') {
num++
}
}
return num
}
// 执行用时:692 ms, 在所有 JavaScript 提交中击败了33.33%的用户
// 内存消耗:46.7 MB, 在所有 JavaScript 提交中击败了81.48%的用户
// 通过测试用例:64 / 64
复杂度分析:
- 时间复杂度:O(n),其中 n 为神奇字符串 s 的长度。
- 空间复杂度:O(1)。