持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第22天,点击查看活动详情
779. 第K个语法符号
我们构建了一个包含 n
行( 索引从 1 开始 )的表。首先在第一行我们写上一个 0
。接下来的每一行,将前一行中的0
替换为01
,1
替换为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 乍一看,似乎没有什么规律可言,但是看我们做一下拆解:
- 0
- 原:01
- 0
- 1
- 原:01101001
- 0110
- 1001
- 原:01101001
- 0110
- 1001
- **原:0110100110010110 **
- 01101001
- 10010110
- 原: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);
}
};