leetcode
leetcode 1401 ~ 1450
找出第 N 个二进制字符串中的第 K 位

找出第 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 处于中间字符之后,为什么要先找到对称位置的字符,然后再进行翻转?
在这个问题中,字符串Si是由Si-1、'1'和reverse(invert(Si-1))构成的。当k在中间字符之后,它实际上是在reverse(invert(Si-1))部分。这部分字符串是Si-1翻转并反转得到的,所以要找到Si-1中对应的字符位置,需要先计算出对称位置。对称位置计算公式为2^(n-1)*2 - k,即从Si-1的末尾反向计数到k的位置。找到对称位置后,因为这部分是反转的,再根据Si-1的结果反转字符,从而得到正确的字符。
🦆
对于递归解法,如何确保每次递归调用时,k 的值始终有效且不超出当前字符串 Si 的范围?
在递归调用中,每次都是基于当前Si的长度来判断和调整k的值。Si的长度通过公式len(Si) = 2 * len(Si-1) + 1计算,确保每次递归时,k的值都是在有效范围内。如果k在中间字符之前,直接递归调用Si-1,此时k是有效的。如果k在中间字符之后,通过计算对称位置2^(n-1)*2 - k,这个值也会保留在Si-1的有效范围内,因为它是从Si的长度中减去k得到的,所以不会超出Si-1的长度。这样每一步的k都是合法且有效的。
🦆
在计算中间位置时,使用的公式是 middle = 2^(n-1)。这个位置是从1开始计数还是从0开始?
在这个问题的上下文中,位置k是从1开始计数的。因此,使用的公式middle = 2^(n-1)指的是从1开始的位置。这意味着Si的中间位置是从字符串的第1个位置开始计算的第2^(n-1)个位置。例如,如果n=2,则middle = 2^(2-1) = 2,表示S2的第2位是中间位。

相关问题