05 August 2008
On the first row, we write a
. Now in every subsequent row, we look at the previous row and replace each occurrence of 1
0
with 1
0
, and each occurrence of 1
01
with 1
1
.1
10
Given row
and index 1
N
, return the 1
K
-th indexed symbol in row 1
K
. (The values of 1
N
are 1-indexed.) (1 indexed).1
K
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Examples:
Input: N = 1, K = 1
Output: 0
Input: N = 2, K = 1
Output: 0
Input: N = 2, K = 2
Output: 1
Input: N = 4, K = 5
Output: 1
Explanation:
row 1: 0
row 2: 01
row 3: 0110
row 4: 01101001
Note:
1
N
will be an integer in the range 1
[1, 30]
.1
K
will be an integer in the range 1
[1, 2^(N-1)]
.在第一行我们写上一个 0。接下来的每一行,将前一行中的0替换为01,1替换为10。给定行数 N 和序数 K,要求返回第 N 行中第 K个字符。(K从1开始)。
可以分解成子问题,选择递归,观察递归书,如下规律
1
2
3
4
5
6
7
8
/* 0
/ \
0 1
/ \ / \
0 1 1 0
/ \ / \ / \ / \
0 1 1 0 1 0 0 1
*/
首先,可以发现每行的前缀完全相同。 不难理解。 因为每2 * L个首字母由相同的L个首字母生成。知道了每一行都有相同长序列的开始部分。 此外,题目保证K为[1,2 ^(N-1)]范围内的整数。,因此结果仅取决于值K。
假设2 ^ L < K <= 2 ^(L + 1)。 2 ^ L是小于K的最大2的幂。 从K-2 ^ L生成Kth数 Kth数也不同于K-2 ^ L 因此我们通过减去2 ^ L将K切换为K-2 ^ L
重复此过程,直到将K变为1, 这意味着总共需要减去K-1次。可以以二进制形式传输K - 1, 这样就可以轻松找到需要转换的次数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public int kthGrammar(int N, int K) {
if(N == 1) {
return 0;
}
if(K % 2 == 0){
if (kthGrammar(N-1, K / 2) == 0) { // 递归
return 1;
}else {
return 0;
}
}else{
if(kthGrammar(N-1,(K+1) / 2) == 0) { // 递归
return 0;
} else {
return 1;
}
}
}
}
更加简短的写法
1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public int kthGrammar(int N, int K) {
K--;
int count = 0;
// Kth number in N row, 由K/2th number in N-1 row决定. 如果 K % 2 == 0,那就与前面相同, 否则相异。 所以Kth会转换x次,x则等于K中bit 1的数量.
while (K != 0) {
K = K & (K - 1); // 消除最后一个1
count++;
}
return count % 2;
}
}
1
2
3
4
5
class Solution {
public int kthGrammar(int N, int K) {
return Integer.bitCount(K - 1) & 1;
}
}