📌  相关文章
📜  从 Stern 的双原子级数中找出第 n 个元素(1)

📅  最后修改于: 2023-12-03 14:49:19.400000             🧑  作者: Mango

从 Stern 的双原子级数中找出第 n 个元素

Stern 的双原子级数是一种非常有趣的数列,它的定义如下:

  • S(0) = 0
  • S(1) = 1
  • S(2n) = S(n)
  • S(2n+1) = S(n) + S(n+1)

根据这个定义,我们可以得到前几项:

0, 1, 1, 2, 1, 3, 2, 3, 1, 4, 3, 5, 2, 5, 3, 4, 1, 5, 4, 7, 3, 8, 5, 7, 2, 7, 5, 8, 3, 7, 4, 5, 1, 6, 5, 9, 4, 11, 7, 10, 3, 11, 8, 13, 5, 12, 7, 9, 2, 9, 7, 12, 5, 13, 8, 11, 3, 10, 7, 11, 4

很容易发现,这个数列中有许多重复的项,因此我们可以采用动态规划的思路来解决这个问题。

具体做法是:用一个数组 $a 存储第 $i$ 位的值,用另外一个数组 $b 存储第 $i$ 位前面有多少个不同的值。初始时,$a_0 = 0, a_1 = 1, b_0 = 0, b_1 = 1$。然后我们从 $i = 2$ 开始,根据上述的递推关系式,计算出 $a_i$,然后比较 $a_i$ 与前面的所有 $a_j (j < i)$ 是否相等,如果相等,则 $b_i = b_{i-1}$,否则 $b_i = b_{i-1} + 1$。

最后,当 $i > n$ 时,直接返回 $a_n$ 即可。

代码如下:

/**
 * @param int $n
 * @return int
 */
function sternSequence($n)
{
    $a = [0, 1];
    $b = [0, 1];
    for ($i = 2; $i <= $n; ++$i) {
        $a[$i] = ($i % 2 == 0) ? $a[$i/2] : $a[($i-1)/2] + $a[($i+1)/2];
        $b[$i] = $b[$i-1] + (($a[$i] == $a[$i-1]) ? 0 : 1);
    }
    return $a[$n];
}

该函数的时间复杂度为 $O(n)$,空间复杂度为 $O(n)$,可以在很短的时间内计算出数列中任意一项的值。

以上是对 Stern 的双原子级数的介绍和解法,希望能对大家有所帮助。