每日一练 · 找出第 N 个二进制字符串中的第 K 位

138 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第8天,点击查看活动详情

一、题目描述:

给你两个正整数 n 和 k,二进制字符串  Sn 的形成规则如下:

S1 = "0" 当 i > 1 时,Si = Si-1 + "1" + reverse(invert(Si-1)) 其中 + 表示串联操作,reverse(x) 返回反转 x 后得到的字符串,而 invert(x) 则会翻转 x 中的每一位(0 变为 1,而 1 变为 0)。

例如,符合上述描述的序列的前 4 个字符串依次是:

S1 = "0" S2 = "011" S3 = "0111001" S4 = "011100110110001" 请你返回  Sn 的 第 k 位字符 ,题目数据保证 k 一定在 Sn 长度范围以内。

 

示例 1:

输入:n = 3, k = 1 输出:"0" 解释:S3 为 "0111001",其第 1 位为 "0" 。 示例 2:

输入:n = 4, k = 11 输出:"1" 解释:S4 为 "011100110110001",其第 11 位为 "1" 。 示例 3:

输入:n = 1, k = 1 输出:"0" 示例 4:

输入:n = 2, k = 3 输出:"1"  

提示:

1 <= n <= 20 1 <= k <= 2n - 1

二、思路分析:

我们可以知道第n行有2^n-1个字符,其中前2^(n-1)-1个字符是上一个字符串的值,第2^(n-1)个是新加的1,后面2^(n-1)-1个字符是上一个字符串翻转取反得来的。 可以使用递归方法

每次递归中三种情况: 1.如果k>2^(n-1),说明它是上一个字符串翻转并invert过来的部分,可以推导得到求出它在上一个字符串的位置索引为2^n-k,并将invert次数加一次,当此时n>1则可以接着递归求下去; 2.如果k<2^(n-1),说明它就是上一次字符串位置k处的字符,没有被invert则不必更新invert次数,当此时n>1则可以接着递归求下去; 3.如果k==2^(n-1),说明他是此时对应的n新增的最中间1,可以结束递归,返回其初始值1。另一种情况递归结束条件为n递归到1了,说明它就是最初始的值0,返回0;

得到其初始值后,再来结合这个值被invert了几次,奇数次则原值0变1或1变0,偶数次就不变直接返回初始值。

三、AC 代码:

class Solution {
    int[] pows=new int[21];
    int invert=0;
    public char findKthBit(int n, int k) {
        for(int i=0;i<=n;i++){
            pows[i]= (int) Math.pow(2, i);
        }
        int m=can(n,k);
        if(invert%2==1){
            if(m==1){
                return '0';
            }
            return '1';
        }else{
            if(m==1){
                return '1';
            }
            return '0';
        }
        
    }

    public int can(int n,int k){
        if(n==1){
            return 0;
        }
        if(k==pows[n]/2){
            return 1;
        }else{
            if(k>pows[n]/2){
                invert++;
                return can(n-1,pows[n]-k);
            }else{              
                return can(n-1,k);
            }
        }
        
    }
}

四、总结:

image.png

掘友们,解题不易,留下个赞或评论再走吧!谢啦~ 💐

希望对你有帮助

期待下次再见~

🌇 点赞 👍 收藏 ⭐留言 📝 一键三连 ~关注从你我做