LeetCode 779.第K个语法符号

LeetCode 779.第K个语法符号

题目描述

在第一行我们写上一个 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)].

解题

直接递归

    第N行第K个数字由第N-1行第(K+1)/2个数字得来,一直递归下去就能得到最初始的数字,然后从最开始的这个数字出发,一路返回,最终就可以推断出要求的数字。比如上一层返回结果为0,那么如果K是奇数,则返回0,如果K是偶数,则返回1;如果上一层返回结果位1,那么结果相反。

class Solution {
public:
    int kthGrammar(int N, int K) {
        if (N<=2) return K-1;
        return kthGrammar(N-1, (K+1)/2) ? K&1 : 1-(K&1);
    }
};
另一种递归

    最一开始就可以知道当前行的数字数目是上一行的两倍,而且,有趣的是,当前行的前半段数字与上一行完全相同,后半段是前半段对应位置的翻转(0变为1,1变为0)。那么如果K大于当前行N对应数字总数S的一半,那么第K个数字的值应该是第(K-S/2)个数字的翻转,该数字与第N-1行第(K-S/2)个数字相同,以此同样可以“溯源”,然后返回过程中推导出当前层目标位置的数字。

class Solution {
public:
    int kthGrammar(int N, int K) {
        if (N<=2) return K-1;
        if (K > (1<<(N-2))) return kthGrammar(N-1, K-(1<<(N-2))) ^ 1;
        else return kthGrammar(N-1, K);
    }
};
更巧妙的循环

    上面的分析中得知,当前行的所有数字与下一行前半段是相同的,这一点引申一下就是,对于第N行第K个数字,如果K位于当前行的前半段,那么第N行第K个数字一定等于前面某一行n的第K个数字,此时K位于第n行的后半段,且第n行到第N行的第K个数字都相同。
    上面的分析还得知,如果当前行要求的那个数字位于后半段,那么该数字与前半段对应数字存在“翻转”的关系。由此可以简化我们“溯源”的过程:
    1. 如果当前行要求的位置的数字位于前半段,则直接跳到对应位置在后半段的行。
    2. 如果当前行要求的位置的数字位于后半段(不管是一开始就位于后半段或者由第1步跳到该行),当前行的结果应该是前半段对应位置数字的翻转,而前半段对应数字的求法与当前目标位置的数字求法一致,我们同样可以找到前半段那个对应数字位于后半段的行,以此类推。
    对于当前第N行,总数字数目位 2 N − 1 2^{N-1} 2N1,如果K位于后半段,那么有
2 N − 2 + 1 ≤ K ≤ 2 N − 1 2^{N-2}+1 \leq K \leq 2^{N-1} 2N2+1K2N1
它对应的前半段数字J有:
J = K − 2 N − 2 J = K-2^{N-2} J=K2N2
1 ≤ J ≤ 2 N − 2 1 \leq J \leq 2^{N-2} 1J2N2
如果要保证J同样位于后半段,那么:
2 N − 3 + 1 ≤ J ≤ 2 N − 2 2^{N-3}+1 \leq J \leq 2^{N-2} 2N3+1J2N2
反映在二进制上,就是K对应二进制数的次高位为1。
    我们继续做如下推理:如果K对应二进制的次高位为1表示它对应的前半段位置的数字在上一行同样位于后半段。如果K对应二进制的次高位为0,那么它对应的前半段位置的元素在上一行位于前半段,结合上述第1点描述,那么可以直接跳到对应位置在后半段的行,假设这一行为L,那么:
2 L − 2 + 1 ≤ K ≤ 2 L − 1 2^{L-2}+1 \leq K \leq 2^{L-1} 2L2+1K2L1
即二进制的第L或第L-1位为1,这里又出现了翻转,这里结论就可以引申开来:翻转的次数等于二进制中1的个数。
    但是以上的推理中存在一个缺陷,那就是第N层第K个数字是否位于后半段时,其最高位的位置或许为N或许为N-1,这样无法统一,而再次观察:
2 N − 2 + 1 ≤ K ≤ 2 N − 1 2^{N-2}+1 \leq K \leq 2^{N-1} 2N2+1K2N1
发现:
2 N − 2 ≤ K − 1 ≤ 2 N − 1 − 1 2^{N-2} \leq K-1 \leq 2^{N-1}-1 2N2K12N11
其最高位确定在第N-1位,而且这里减去的1将会“顺延”给J,所以结论就是翻转的次数等同于K-1对应的二进制中1的个数。

class Solution {
public:
    int kthGrammar(int N, int K) {
        int num=0;
        --K;
        while (K){
            if (K&1) ++num;
            K>>=1;
        }
        return num % 2;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值