持续创作,加速成长!这是我参与「掘金日新计划 · 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);
}
}
}
}
四、总结:
掘友们,解题不易,留下个赞或评论再走吧!谢啦~ 💐
希望对你有帮助
期待下次再见~
🌇 点赞 👍 收藏 ⭐留言 📝 一键三连 ~关注从你我做