【递归】二进制字符串中的第K位

题目描述

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

  1. S1 = "0"
  2. 当 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 长度范围以内。

例如输入:n = 3, k = 1,会输出:"0"。因为S3 为 "0111001",其第 1 位为 "0" 。

输入格式

第一行2个正整数:N K。N 范围[2, 30];

输出格式

1或0

输入/输出例子1

输入:

4 11

输出:

1

解题思路

这题的思路非常巧妙,通过观察我们知道二进制字符串Sn中间位都是1,左右两边是取反后并对称。所以,如果某一位处在后半段,我们可以找到前半段对应数位取反即可求到答案。这样我们可以把问题规模变小,当字符串长度为1或者是要求的数位处于S的中间位时我们就可以得到答案,然后结束。

因此我们可以定义递归函数,有三个组成要素,一个是字符串长度l,一个是我们要求的位k,还有一个是是否进行了取反操作rv,rv=1表示做了取反,rv=0表示没有取反。对于两个结束条件的返回值,先讨论通过若干次递归,问题规模变小,使得l=1的情况,对于这种情况如果没有取反操作的,我们观察S1可知,返回0(此时rv也是为0)。如果是后半段往前找的,就要取反,函数传的参数rv=1,返回1。归纳起来就是,如果长度为1时,返回rv。再看要求的数位处于S的中间位的情况,如果k在原字符串中本来就是处于前半段的,且折半后k在中间位就返回1。如果k在原字符串中本来就是处于后半段的,将其对应到前半段的位置l-k+1,且折半后在中间位就返回0(此时要取反)。所以返回的应该是1-rv。如果没达到结束条件,就进行折半和比较,直到到达结束条件为止。

AC代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n,k;
int dg(int l,int k,int rv){
	if(l==1) return rv;
	int m=(l+1)/2;
	if(m==k) return 1-rv;
	if(m<k) dg(l/2,l-k+1,1-rv);
	else dg(l/2,k,rv);
}
int main(){
	cin>>n>>k;
	int ln=0;
	for(int i=1;i<=n;i++) ln=ln*2+1;
	cout<<dg(ln,k,0);
	return 0;
}
相关推荐
mjhcsp2 小时前
C++ 循环结构:控制程序重复执行的核心机制
开发语言·c++·算法
立志成为大牛的小牛2 小时前
数据结构——四十一、分块查找(索引顺序查找)(王道408)
数据结构·学习·程序人生·考研·算法
xier_ran2 小时前
深度学习:RMSprop 优化算法详解
人工智能·深度学习·算法
地平线开发者3 小时前
不同传感器前中后融合方案简介
算法·自动驾驶
Mr_WangAndy3 小时前
C++_chapter15_C++重要知识点_lambda,initializer_list
c++·lambda·初始化列表
地平线开发者3 小时前
征程 6X 常见 kernel panic 问题
算法·自动驾驶
Maple_land3 小时前
第1篇:Linux工具复盘上篇:yum与vim
linux·运维·服务器·c++·centos
hggngx548h4 小时前
有哪些C++20特性可以在Dev-C++中使用?
开发语言·c++·c++20
com_4sapi4 小时前
2025 权威认证头部矩阵系统全景对比发布 双榜单交叉验证
大数据·c语言·人工智能·算法·矩阵·机器人