LeetCode探索(167):481-神奇字符串

132 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第32天,点击查看活动详情

题目

神奇字符串 s 仅由 '1''2' 组成,并需要遵守下面的规则:神奇字符串 s 的神奇之处在于,串联字符串中 '1''2' 的连续出现次数可以生成该字符串。

s 的前几个元素是 s = "1221121221221121122……" 。如果将 s 中连续的若干 12 进行分组,可以得到 "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)。

参考