📌  相关文章
📜  查找 Mth 字典序最小的二进制字符串,没有两个相邻的 1(1)

📅  最后修改于: 2023-12-03 15:40:22.470000             🧑  作者: Mango

查找 Mth 字典序最小的二进制字符串,没有两个相邻的 1

这个问题可以通过递归来解决。假设我们已经知道了长度为 $n$ 的二进制字符串中,没有两个相邻的 1 的个数 $f(n)$,则对于长度为 $n+1$ 的二进制字符串,其可以由以下两种情况得到:

  1. 在长度为 $n$ 的字符串的末尾添加一个 0,此时可以直接得到一个没有两个相邻的 1 的长度为 $n+1$ 的字符串;
  2. 在长度为 $n-1$ 的字符串的末尾添加一个 10,此时可以得到一个以 10 结尾的长度为 $n+1$ 的字符串,但是这个字符串的倒数第二个字符必须为 0,否则就会出现相邻的 1。

因此,对于长度为 $n+1$ 的字符串,其可以由长度为 $n$ 的字符串和长度为 $n-1$ 的字符串得到,即 $f(n+1) = f(n) + f(n-1)$。

可以发现,这就是一个斐波那契数列,因此我们可以通过斐波那契数列递推公式来解决这个问题。

实现细节见以下代码(使用了 Python 3 的 f-string):

def find_str(m: int) -> str:
    if m == 1:
        return '0'

    # 通过斐波那契数列求出最小的 n,使得 f(n) >= m
    f1, f2 = 1, 2
    while f2 < m:
        f1, f2 = f2, f1 + f2
    n = f2 - f1

    # 根据最小的 n,从后向前构造字符串
    ans = ['0'] * (n + 1)
    for i in range(n, -1, -1):
        if m >= f2:
            ans[i] = '1'
            m -= f2
        f2, f1 = f1, f2 - f1

    return ''.join(ans)

此时时间复杂度为 $O(\log m)$。

参考文献: