内卷地狱

1545. Find Kth Bit in Nth Binary String

Edit Me

Problem

Given two positive integers n and k, the binary string Sn is formed according to the following rules:

  • S1 = "0"
  • When i > 1: Si = Si-1 + "1" + reverse(invert(Si-1))

where + denotes concatenation, reverse(x) returns the string x reversed, and invert(x) flips every bit in x (0 becomes 1 and 1 becomes 0).

The first 4 strings in this sequence are:

  • S1 = "0"
  • S2 = "011"
  • S3 = "0111001"
  • S4 = "011100110110001"

Return the k-th bit in Sn. It is guaranteed that k is within the valid range for Sn.

Solution

My first attempt was a brute-force approach — directly generating Sn. However, when n is large, Sn becomes extremely long, causing memory overflow.

/**
 * @param {number} n
 * @param {number} k
 * @return {character}
 */
var findKthBit = function (n, k) {
  var reverseR = function (input) {
    return input
      .split("") // 拆分成数组 ["0", "1", "1", "1", "0"]
      .map((char) => char ^ 1) // 翻转每一位: [1, 0, 0, 0, 1]
      .reverse() // 反转数组顺序: [1, 0, 0, 0, 1]
      .join(""); // 拼回字符串 "10001"
  };
  let S = "0";
  for (let i = 1; i < n; i++) {
    S = S + "1" + reverseR(S);
  }
  return S[k - 1];
};

I then tried a mathematical bit-flip approach. Observing Si=Si1+"1"+reverse(invert(Si1))S_i = S_{i-1} + "1" + \text{reverse}(\text{invert}(S_{i-1})):

Length pattern: Sn=2n1|S_n| = 2^n - 1.

  • For example, S1S_1 has length 211=12^1-1=1, and its middle bit is position 11.
  • S2S_2 has length 221=32^2-1=3, and its middle bit is position 22.
  • S3S_3 has length 231=72^3-1=7, and its middle bit is position 44.

Three cases for the position of k:

  • Left half (k &lt; mid): This is an exact copy of Sn1S_{n-1}, so we simply ask "what is the kk-th bit of Sn1S_{n-1}?"
  • Middle (k=midk = mid): By the construction rule, this bit is always "1".
  • Right half (k &gt; mid): This is the most elegant part. The right half is the reverse-invert of Sn1S_{n-1}.

Because of the reverse, the 1st character of the right half corresponds to the last character of the left half, and so on.

The mapping formula is: Sn[k]=invert(Sn1[2nk])S_n[k] = \text{invert}(S_{n-1}[2^n - k]).

For example, to find the 6th bit in S3S_3 (length 7), it corresponds to the result of inverting the 236=22^3 - 6 = 2nd bit of S2S_2.

var findKthBit = function (n, k) {
  let flip = false; // 记录需要取反的次数
  while (n > 1) {
    let mid = 1 << (n - 1); // 2^(n-1)
    if (k === mid) {
      // 中间位固定为 1
      let res = 1;
      return (flip ? res ^ 1 : res).toString();
    } else if (k > mid) {
      // 如果在右侧,镜像到左侧,并增加一次取反
      k = 2 * mid - k;
      flip = !flip;
    }
    // 如果在左侧,直接继续看 n-1
    n--;
  }
  // 最终回到 S1,S1 是 "0"
  let res = 0;
  return (flip ? res ^ 1 : res).toString();
};

Why Is mid Equal to 2n12^{n-1}?

We can derive the center point (mid) by computing the total length of SnS_n.

Computing the length of SnS_n: Let LnL_n denote the length of the nn-th string SnS_n. From the problem rules:

  • S1="0"S_1 = "0", so L1=1L_1 = 1
  • Sn=Sn1+"1"+modified Sn1S_n = S_{n-1} + "1" + \text{modified } S_{n-1}

The length recurrence is: Ln=Ln1(left half)+1(middle)+Ln1(right half)L_n = L_{n-1} (\text{left half}) + 1 (\text{middle}) + L_{n-1} (\text{right half}) i.e., Ln=2×Ln1+1L_n = 2 \times L_{n-1} + 1

Listing out the values:

  • L1=1L_1 = 1
  • L2=2×1+1=3L_2 = 2 \times 1 + 1 = 3
  • L3=2×3+1=7L_3 = 2 \times 3 + 1 = 7
  • L4=2×7+1=15L_4 = 2 \times 7 + 1 = 15

Pattern: Ln=2n1L_n = 2^n - 1

2. Why Do We Search This Way?

Think of it like finding a specific point on an infinitely folded paper strip:

  • Old approach (simulation): Fold a blank sheet of paper 20 times to create an enormously long strip, then count from the beginning to the kk-th point.
  • New approach (backtracking/iteration): Look at the already "folded" paper (SnS_n) and ask: is this point kk to the left or right of the fold?
    • If it is to the right of the fold, "unfold" it back to the left (mirror mapping) and record that it was flipped once (flip = !flip).
    • If it is to the left, just look directly at the left half.
    • Now the paper is half the size (n--), and you repeat the process until you land exactly on the fold (k === mid) or the paper shrinks to its smallest possible size (n=1).

3. If We Are in the Right Half and S[k]=0, Does Flipping Over Mean S[k]=1?

Why does "flipping over" give us 1?

According to the problem, the right half of SiS_i is: reverse(invert(Si1))\text{reverse}(\text{invert}(S_{i-1})). There are two operations here:

  • Invert: 010 \to 1, 101 \to 0.
  • Reverse: positions are mirrored left-to-right.

So if we see a 0 in the right half and trace it back through these two operations:

  • Because of invert: it was a 1 before being flipped.
  • Because of reverse: its corresponding position is the symmetric point in the left half.

贡献者


这篇文章有帮助吗?

最近更新

Involution Hell© 2026 byCommunityunderCC BY-NC-SA 4.0CCBYNCSA