丑数
date: 2021-02-04T09:17:30+08:00
可以采用动态规划的想法!
第n个丑数$x_n$,它必然为一下三种情况之一:
$$
x_n=
\left{ \begin{array}{rcl}
x_a \times 2 \
x_b \times 3 \
x_c \times 5\
\end{array}\right.
$$
其中$x_a , x_b ,x_c $是未知数。
为了保证不会遗漏某个丑数,$x_n$必然等于: $$ x_n=min{x_a \times 2,x_b \times 3,x_c \times 5 } $$
这里我们需要明确的是一个丑数乘上2或3或5还是一个丑数
这里因为我们要在${x_a \times 2,x_b \times 3, x_c \times 5}$中挑选出最小的一个丑数,我们可以这样考虑,假设存在三个数组,分别用第一个丑数乘上2,3,5
|
|
那么, 最终的丑数序列实际上就是这 3 个有序序列对的合并结果, 计算丑数序列也就是相当于 合并 3 个有序序列。 合并 3 个有序序列
合并 3 个有序序列, 最简单的方法就是每一个序列都各自维护一个指针, 然后比较指针指向的元素的值, 将最小的放入最终的合并数组中, 并将相应指针向后移动一个元素。 这也就是:
|
|
合并过程中重复解的处理
nums2, nums3, nums5 中是存在重复的解的, 例如 nums2[2] == 32, nums3[1] == 23 都计算出了 6 这个结果, 所以在合并 3 个有序数组的过程中, 还需要跳过相同的结果, 这也就是为什么在比较的时候, 需要使用 3 个并列的 if… if… if… 而不是 if… else if… else 这种结构的原因。 当比较到元素 6 时, if (dp[i] == dp[p2] * 2)…if (dp[i] == dp[p3] * 3)… 可以同时指向 nums2, nums3 中 元素 6 的下一个元素。
最终的代码:
|
|