找出第 N 个二进制字符串中的第 K 位
难度:
标签:
题目描述
代码结果
运行时间: 22 ms, 内存: 15.9 MB
/*
* 思路:
* 1. 使用流来生成二进制字符串 S_n。
* 2. 用流的方法进行字符反转和反转。
* 3. 最后通过索引查找第 k 位字符。
*/
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class Solution {
public char findKthBit(int n, int k) {
String sn = generateSn(n);
return sn.charAt(k - 1);
}
private String generateSn(int n) {
if (n == 1) return "0";
String prev = generateSn(n - 1);
String invertedReversed = new StringBuilder(prev)
.reverse()
.toString()
.chars()
.mapToObj(c -> (char) (c == '0' ? '1' : '0'))
.map(String::valueOf)
.collect(Collectors.joining());
return prev + "1" + invertedReversed;
}
}
解释
方法:
此题解采用了递归的方法来寻找第k位字符,避免了直接构造整个字符串Si的复杂性。首先,每个字符串Si的长度是前一个字符串长度的二倍加一,即len(Si) = 2 * len(Si-1) + 1。对于任何Si,其结构可以分解为Si-1 + '1' + reverse(invert(Si-1))。中间的字符总是'1',位于位置2^(n-1)。基于k的位置,算法将问题分为三种情况:1) 如果k正好是中间位置,则答案是'1'。2) 如果k在中间字符之前,问题就变成在Si-1中找第k位,可以递归调用Si-1。3) 如果k在中间字符之后,需要在反转并翻转的Si-1中寻找对应的位,这转换为在Si-1中找第(2^(n-1)*2 - k)位,且需要根据结果翻转字符。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
递归函数中,如果 k 处于中间字符之后,为什么要先找到对称位置的字符,然后再进行翻转?
▷🦆
对于递归解法,如何确保每次递归调用时,k 的值始终有效且不超出当前字符串 Si 的范围?
▷🦆
在计算中间位置时,使用的公式是 middle = 2^(n-1)。这个位置是从1开始计数还是从0开始?
▷