

思路:递归+倒推
- 一个经典逆向思维,假设目标位置为1(或0),倒退回第一行检查答案是否正确,毕竟只有两种数字非此即彼。
- 构建一个递归函数DFS(row,col,cur),表示第row行第col列的数字为cur;
- 根据构造规则,若奇数列位置为1,或偶数列位置为0,那上一行对应位置应为1,反之为0;
- 上一行对应位置与当前行位置关系满足colrow−1=⌊2col+1⌋;
- 当回到第一行时返回结果,若此时结果为0说明假设正确返回假设数字,否则说明假设错误返回另一个数字。
Java
class Solution {
public int kthGrammar(int n, int k) {
return DFS(n, k, 1) == 0 ? 1 : 0;
}
int DFS(int row, int col, int cur) {
if (row == 1)
return cur;
if((col % 2 == 1 && cur == 1) || (col % 2 == 0 && cur == 0))
return DFS(row - 1 , (col + 1) / 2, 1);
else
return DFS(row - 1, (col + 1) / 2, 0);
}
}
- 时间复杂度:O(n)
- 空间复杂度:O(1)
C++
class Solution {
public:
int kthGrammar(int n, int k) {
return DFS(n, k, 1) == 0 ? 1 : 0;
}
int DFS(int row, int col, int cur) {
if (row == 1)
return cur;
if((col % 2 == 1 && cur == 1) || (col % 2 == 0 && cur == 0))
return DFS(row - 1 , (col + 1) / 2, 1);
else
return DFS(row - 1, (col + 1) / 2, 0);
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(1)
Rust
impl Solution {
pub fn kth_grammar(n: i32, k: i32) -> i32 {
if Self::DFS(n, k, 1) == 0 {
return 1;
}
0
}
fn DFS(row: i32, col: i32, cur: i32) -> i32 {
if (row as i32 == 1) {
return cur as i32;
}
if((col as i32 % 2 == 1 && cur as i32 == 1) || (col as i32 % 2 == 0 && cur as i32 == 0)) {
return Self::DFS(row - 1 , (col + 1) / 2, 1) as i32;
}
else {
return Self::DFS(row - 1, (col + 1) / 2, 0) as i32;
}
}
}
- 时间复杂度:O(n)
- 空间复杂度:O(1)
思路二:找规律+位运算
- 这个思路是怎么推过来的不知道,但规律是这样出来的……
- 首先可以发现每一行的前几位都是上一行的内容,所以第k个位置的内容和行数无关;
- 这个序列走向是0110100110…
- 若从0开始索引,索引和对应数字的对应关系如下:
|索引|数字|
|---|---|
|0|0|
|1|1|
|2|1|
|3|0|
|4|1|
|5|0|
|6|0|
|7|1|
|……|……|
- 为什么要从0开始呢:
|索引|索引的二进制|索引二进制中1的数量|数字|
|---|---|---|---|
|0|0|0|0|
|1|1|1|1|
|2|10|1|1|
|3|11|2|0|
|4|100|1|1|
|5|101|2|0|
|6|110|2|0|
|7|111|3|1|
|……|……|……|……|
- 发现当前位数字只和索引二进制表示中1的数量有关,数量为偶时为0,数量为奇时为1。Coun
Java
class Solution {
public int kthGrammar(int n, int k) {
return Integer.bitCount(k - 1) & 1;
}
}
- 时间复杂度:O(1),取决于
bitCount()函数的复杂度
- 空间复杂度:O(1)
bitCount()
C++
class Solution {
public:
int kthGrammar(int n, int k) {
return __builtin_popcount(k - 1) & 1;
}
};
- 时间复杂度:O(1),取决于
__builtin_popcount()函数的复杂度
- 空间复杂度:O(1)
__builtin_popcount()
Rust
impl Solution {
pub fn kth_grammar(n: i32, k: i32) -> i32 {
(k - 1).count_ones() as i32 & 1
}
}
- 时间复杂度:O(1),取决于
()函数的复杂度
- 空间复杂度:O(1)
总结