• 779. 第K个语法符号


    思路

    首先多扩充几行看看有什么规律:

    1: 0
    2: 0 1
    3: 0 1 1 0
    4: 0 1 1 0 1 0 0 1
    5: 0 1 1 0 1 0 0 1 1 0 0 1 0 1 1 0
    6: 0 1 1 0 1 0 0 1 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 1
    ......
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    发现有以下规律:

    1. n行的 2 n − 1 2^{n-1} 2n1个数,与第n+1行的前 2 n − 1 2^{n-1} 2n1个数是相同的
    2. 将第n行的 2 n − 1 2^{n-1} 2n1个数的序数划分为两个区间: [ 1 , 2 n − 2 ] ,   [ 2 n − 2 + 1 , 2 n − 1 ] [1,2^{n-2}], \ [2^{n-2}+1, 2^{n-1}] [1,2n2], [2n2+1,2n1],对于第i个数, i ∈ [ 1 , 2 n − 2 ] i \in [1, 2^{n-2}] i[1,2n2],第 i + 2 n − 2 i+2^{n-2} i+2n2个数一定是其取反得到的。

    通过规律1和2,我们可以做如下操作:

    1. 用一个变量count记录翻转次数,表示下标k进行了几次转换
    2. k在第n行中,且 k ∈ [ 2 n − 2 + 1 , 2 n − 1 ] k \in [2^{n-2}+1, 2^{n-1}] k[2n2+1,2n1],我们进行一次进行一次翻转,将k修改为前半段对应的下标,并令count++
    3. k在第n行中,但是下标不在后半区间,那么k一定是在某一行的后半段的区间中,在该行内做转换。这样做成立的原因就是前面行中的数字与后面行中的数字一定是相等的。
    4. 每次进行区间翻转时,实际上就是减去区间长度的一半。
    5. 我们可以令下标从0开始,并令k = k-1,做翻转的操作其实就是k减去它最高位1所代表的值,直至减至k=0位置。实际上就是记录k-1二进制表示中1的个数。
    6. count为奇数时说明翻转了奇数次才变为0,则原来的数为1;反之原来的数为0

    实际上就是判断k-1二进制表示中1是奇数个还是偶数个,奇偶校验

    代码如下:

    class Solution {
    public:
        int kthGrammar(int n, int k) {
            int count = 0; //记录反转了几次
            k-=1;
            while(k > 0){
                //每次减去它的lowbit;
                k = k - (k&(-k));
                count++;
            }
            return count % 2 == 1 ? 1: 0;  
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    C语言:扫雷小游戏
    常规业务如何做到幂等性
    使用 Apache SkyWalking 进行 Spring Cloud 应用的分布式追踪与监控:完整教程
    基于postgis实现坐标转换的几个函数
    携创教育:成人自考本科全部流程!
    搜维尔科技:“虚实结合” 体验式人机验证技术,助力通用汽车开启研发新篇章
    图的基本知识
    二分查找以及扩展
    软件外包开发需求文档编写
    【C#】数组string类型输出
  • 原文地址:https://blog.csdn.net/qq_40878398/article/details/127422343