5484. 找出第 N 个二进制字符串中的第 K 位
题目描述:
给你两个正整数 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
解题思路:
1)、按照题目的描述将字符串构造出来;
实现1(超时的方法):
char findKthBit2(int n, int k) {
vector<int> vCur(1,1) ;
vector<int> vNext ;
int i = 1 ;
int tmp = vCur.size() ;
while (i < n)
{
vNext = vCur ;
reverse(vCur.begin() , vCur.end()) ;
vNext.insert(vNext.end() , vCur.begin(), vCur.end()) ;
if (tmp & 1)
vNext[tmp] ++ ;
else
vNext[tmp - 1] ++ ;
vCur = vNext ;
}
i = 0 ;
int sum = 0 ;
for (int mm : vNext)
{
sum += mm
if (sum > k)
{
if (i & 1) return '1' ;
else return '0' ;
break ;
}
i ++ ;
}
return '0' ;
}
实现2(超时的方法):
//翻转后逆转
string reverseInvert(string s)
{
string str = "" ;
for (char c : s)
{
if (c == '0') str = '1' + str ;
else str = '0' + str ;
}
return str ;
}
char findKthBit(int n, int k) {
string sCur = "0" , sNext = "" ;
int i = 1 ;
while (i < n)
{
cout << sCur << endl ;
sNext = sCur + "1" + reverseInvert(sCur);
sCur = sNext ;
i ++ ;
}
cout << sCur << endl ;
return sCur[k] ;
}
实现3(leecode 的 汪乐平 大佬)
class Solution {
//string s[21],t[21];
public:
char findKthBit(int n, int k) {
string sCur = "0" , tCur = "1";
string sNext , tNext ;
int i = 1 ;
while(i < n)
{
sNext = sCur;
sNext += '1';
sNext += tCur;
tNext = sCur;
tNext += '0';
tNext += tCur;
sCur = sNext ;
tCur = tNext ;
i ++ ;
}
return sCur[k-1];
}
};
解题思路2(利用回文的特点)
1)、利用回文在相对于中间位置是对称的;
2)、因为相对于中心位置,右边的数据又是左边的逆转;('0' 换成 '1' , '1' 换成 '0'
);
代码实现:
class Solution {
vector<int> kv ;
public:
//统计`Si` 的字符的个数;每一个`Si `都是呈现中心对称的。
Solution()
{
kv.push_back(1) ;
int tmp = 1 , i = 1 ;
while (i ++ < 21)
{
tmp = (tmp << 1) + 1 ;
kv.push_back(tmp) ;
}
}
//change要计算翻转的次数
char findKthBitChange(int k , int change) {
if (k == 1) return (change & 1) ? '1' : '0' ;
int i = 0 ;
while (k > kv[i ++]) ;
i -- ;
if (k == kv[i] || k == kv[i - 1] + 1) return (change & 1)? '0' : '1' ;
else
{
k = kv[i] - k + 1 ;
change ++ ;
//cout << change << endl ;
return findKthBitChange(k , change) ;
}
}
char findKthBit(int n, int k) {
if (k == 1) return '0' ;
else return findKthBitChange(k , 0) ;
}
};
复杂度计算:
时间复杂度O(log n)
;
空间复杂度 O(1)
;因为 增加的是常数 10个额外的空间。