简单易懂!找规律 779. 第K个语法符号

62 阅读1分钟

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

779. 第K个语法符号

我们构建了一个包含 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 <= 2n - 1

解题思路

根据题目可知,当 n = 4的时候

  • 第一行 0
  • 第二行 01
  • 第三行 0110
  • 第四行 01101001
  • 第五行 0110100110010110
  • 第六行 01101001100101101001011001101001 乍一看,似乎没有什么规律可言,但是看我们做一下拆解:
  1. 0
  2. 原:01
    • 0
    • 1
  3. 原:01101001
    • 0110
    • 1001
  4. 原:01101001
    • 0110
    • 1001
  5. **原:0110100110010110 **
    • 01101001
    • 10010110
  6. 原:01101001100101101001011001101001
    • 0110100110010110
    • 1001011001101001

我们把求解出来的(除了第一个进行拆解之后):

发现每一行的前半段就是上一行,后半段就是上一行的每个值反过来(0变1,1变0)

那么我们的思路就来了:

  • 如果 K > (2的N-1次方) / 2
    • 那么K所在位置是后半段
    • 可以先算出K相对于后半段的位置,然后找出上一行这个位置的值,把值反过来
  • 反之
    • K所在位置是前半段
    • 所对应的值就是上一行的第K个值

解法:

递归 + 找规律

var kthGrammar = function(N, K) {
    if(N === 1)return 0;

    // 计算当前行的长度:2的N-1次方
    var length = 2 ** (N - 1);

    // 如果K大于长度的一半,就是K所在位置是后半段
    if(K > length / 2){

        // 先得到上一行的值,位置是K相对于后半段的位置
        var val = kthGrammar(N - 1, K - length / 2);

        // 然后把值反过来
        return val === 0 ? 1 : 0;
    }
    // 否则前半部分
    else{

        // 值就是上一行K位置的值
        return kthGrammar(N - 1, K);
    }
};