题目:我们把只包含因子 2、3 和 5 的数称为丑数(Ugly Number)。求按从小到大的顺序的第 1500 个丑数。例如,6、8 都是丑数,但 14 不是,因为它包含因子 7。习惯上我们把 1 当作第一个丑数。
思路 1:从小到大遍历正整数
最直接的思路是:从小到大遍历正整数,一个一个判断是不是丑数,直到第 1500 个为止。这个算法需要判断某个正整数是不是丑数,如何判断呢?连续除以 2,直到余数不等于 0 为止;连续除以 3,直到余数不等于 0 为止;连续除以 5 直到余数不等于 0 为止;最后剩下的数字如果等于 0 则为丑数,否则不是丑数。
这个算法的缺陷在于,需要判断很多不是丑数的正整数,时间效率不是太高。
思路 2:利用生成丑数的规律
上一种思路的缺陷在于需要判断很多不是丑数的正整数,如何避免这种缺陷呢?我们可以利用丑数的生成规律:丑数总是由丑数乘 2、3 或 5 生成的。我们通过举例来进一步分析一下:
- 通过乘 2 所生成的丑数有:1*2、2*2、3*2、4*2、5*2、6*2、8*2、9*2、10*2、12*2、……
- 通过乘 3 所生成的丑数有:1*3、2*3、3*3、4*3、5*3、6*3、8*3、9*3、10*3、12*3、……
- 通过乘 5 所生成的丑数有:1*5、2*5、3*5、4*5、5*5、6*5、8*5、9*5、10*5、12*5、……
但是我们需要找到第 1500 个丑数,也就是说丑数需要按顺序排放。使用一个数组存放丑数,然后可以利用 3 个游动指针 $T_2$、$T_3$ 和 $T_5$分别来记录数组中 2、3 和 5 的当前的最小丑数。每次比较 $T_2*2$、$T_3*3$ 和 $T_5*5$ 的大小,将最小的作为新的丑数放入数组中,并使相应的游动指针后移一位。
实现
1 | public class Solution { |