LeetCode探索(156):779-第K个语法符号

120 阅读1分钟

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

题目

我们构建了一个包含 n 行( 索引从 1 开始 )的表。首先在第一行我们写上一个 0。接下来的每一行,将前一行中的0替换为011替换为10

  • 例如,对于 n = 3 ,第 1 行是 0 ,第 2 行是 01 ,第3行是 0110

给定行数 n 和序数 k,返回第 n 行中第 k 个字符。( k 从索引 1 开始

示例 1:

输入: n = 1, k = 1
输出: 0
解释: 第一行:0

示例 2:

输入: n = 2, k = 1
输出: 0
解释: 
第一行: 0 
第二行: 01

示例 3:

输入: n = 2, k = 2
输出: 1
解释:
第一行: 0
第二行: 01

提示:

  • 1 <= n <= 30
  • 1 <= k <= 2^(n - 1)

思考

本题难度中等。

首先是读懂题意。给出一个包含 n 行的表,给定行数 n 和序数 k,返回第 n 行中第 k 个字符( k 从索引 1 开始)。

观察:

0
01
0110
01101001
01101001 10010110
01101001 10010110 10010110 01101001

找规律:

  • 第 n 行的数字个数是 2^(n-1),是上一行数字的2倍。

  • 每一行是由 上一行的数字 + 与上一行相反的数字 组成。

那么,我们可以使用递归的方法。如果 k 超过上一行的数字个数,则与上一行的数值相反;否则,与上一行的数值相同。

解答

方法一:找规律、递归

/**
 * @param {number} n
 * @param {number} k
 * @return {number}
 */
var kthGrammar = function(n, k) {
  if (k == 1) {
    return 0
  }
  // 如果k超过上一行的数字个数,则与上一行值相反
  if (k > (1 << n - 2)) {
    return 1 ^ kthGrammar(n - 1, k - (1 << n - 2))
  } else { // 与上一行值相同
    return kthGrammar(n - 1, k)
  }
}
// 执行用时:68 ms, 在所有 JavaScript 提交中击败了20.00%的用户
// 内存消耗:40.8 MB, 在所有 JavaScript 提交中击败了82.22%的用户
// 通过测试用例:55 / 55

复杂度分析:

  • 时间复杂度:O(n),其中 n 为题目给定表的行数。
  • 空间复杂度:O(n),其中 n 为题目给定表的行数,主要为递归的空间开销。

参考