1. 题目
在第一行我们写上一个 0。接下来的每一行,将前一行中的0替换为01,1替换为10。
给定行数 N 和序数 K,返回第 N 行中第 K个字符。(K从1开始)
例子:
输入: N = 1, K = 1 输出: 0
输入: N = 2, K = 1 输出: 0
输入: N = 2, K = 2 输出: 1
输入: N = 4, K = 5 输出: 1
解释:
第一行: 0
第二行: 01
第三行: 0110
第四行: 01101001
2. 解题思路
这题可以通过画图由下至上反推来理清思路,以5层为例讲解思路:
如上图所示,每一层数字个数total与层数n之间满足关系:
t
o
t
a
l
=
2
(
n
−
1
)
{total=2^{(n-1)}}
total=2(n−1)。
通过观察,我们可以得知,我们要寻找的每一个数都是一个数对的第一个数或者第二个数。什么意思呢,比如我们要找第5层的第9个数,我们将第五层的数从前往后按照2个数为一组组成一个数对(如上图红色波浪线所示),然后可以发现第9个数处于第 ( 9 / 2 ) + 1 = 5 (9/2)+1=5 (9/2)+1=5个数对中,而9是奇数,所以是在第5层的第5个数对的第一个数,即1。
同理,如果我们要找第4层的第6个数,可以发现他处于第4层的第 ( 6 / 2 ) = 3 (6/2)=3 (6/2)=3个数对中,并且,6是偶数,故我们要找的数是0。
当然这是通过我们观察得到他的结果,那么通过引入这个数对的概念怎么来解这题呢?
试想下如果我们知道了我们要找的数处于某一层的第某个数对,并且知道是这个数对的第一个数还是第二个数,同时我们又知道了这个数对对应上一层的数字,那么是不是可以从上一层数字反推得到这个数对的结果呢?
还是拿第5层第9个数举例子,这个数处于第5层的第5个数对中,而且是这个数对的第一个数,同时我们知道这个数对上一层对应的数字是1,同时由题意知,上一层的1对应下一层的(1,0),所以我们能得到第5层第9个数就是1了。
那么现在有什么问题呢?问题就在于我们不知道我们要寻找数字对应本层数对对应上一层的数字。欸,想一想,我们的函数是干嘛的?是不是来寻找某一层第几个数的,那我是不是可以直接调用我们这个找数函数来找到数对上一层对应的数字了吗?
这就用到了递归了,我们成功找到了寻找某一层某个数的子问题:寻找这个数对应数对上一层的数。那么变量呢?变量自然就是层数和要寻找的第k个数了。边界条件也能很容易想到,就是层数为1。
通过上述思路分析,编写代码如下:
3. 代码
class Solution {
public:
int kthGrammar(int n, int k) {
if (n == 1) return 0;
int ans;
int last_ans;
//奇偶
if (k%2 == 0){
last_ans = kthGrammar(n-1, k/2);
if (last_ans == 1){//上一层是0 or 1,再结合这层要选择的数处于第1位还是第二位去判断
ans = 0;
}
else{
ans = 1;
}
}
else{
last_ans = kthGrammar(n-1, k/2+1);
if (last_ans == 1){
ans = 1;
}
else{
ans = 0;
}
}
return ans;
}
};