第K个语法符号
题目来源:leetcode
在第一行我们写上一个 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
注意:
N 的范围 [1, 30].
K 的范围 [1, 2^(N-1)].
方法一:
题解思路:
1、每一行的个数是2^(N-1);
2、拿第三行和第四行举例:第四行前一半的数和第三行相同,后一半的数等于第三行数取反所得。
代码:
// static int M(int N,int K)
//{
// if (N==1)
// {
// return 0;
// }
// int t = Convert.ToInt32(Math.Pow(2, N - 2));//就是2的N-2次方
// if (K<=t)
// {
// return M(N - 1, K);
// }
// else
// {
// return M(N - 1, K - t) == 1 ? 0 : 1;
// }
//}
static void Main(string[] args)
{
// Console.WriteLine("输入N");
// int N = Convert.ToInt16(Console.ReadLine());
// Console.WriteLine("输入K");
// int K = Convert.ToInt16(Console.ReadLine());
//Console.WriteLine( M(N, K));
}
方法二:
思路分析:N的取值范围是 [1, 30],意味着K的取值可能达到230,这将是一个非常大的数,因此想构造出这个序列然后直接找出第K未是非常不现实的。首先我们来看一下这棵满二叉树排序序号结构
//序号
// 1
// / \
// 1 2
// / \ / \
// 1 2 3 4
// / \ / \ / \ / \
//1 2 3 4 5 6 7 8
不难发现一个规律:(K + 1) / 2是K的父节点所在的序号。
再来看一下01值的分布图
//01排列
// 0
// / \
// 0 1
// / \ / \
// 0 1 1 0
// / \ / \ / \ / \
//0 1 1 0 1 0 0 1
可以再得到一个规律,如果K是奇数,则K的状态与K的父节点的状态相同,否则K的状态与K的父节点状态相反。
所以我们先利用递归求得K的父节点,然后根据K的奇偶性求出K的值。
代码:
class Solution {
public:
int kthGrammar(int N, int K) {
if (N == 1){//第一层:树的根
return 0;
}
//第一步:先求出当前K的父节点状态(注意bool值默认0是false,1是true)
bool father = kthGrammar(N - 1, (K + 1) / 2);
//第二步:根据K的奇偶性求出当前K的状态
if (K % 2 == 1){
return father;
}
else{
return !father;
}
}
};