# 题目描述
把只包含质因子 2、3
和 5
的数称作丑数(Ugly Number)。例如 6、8
都是丑数,但 14
不是,因为它包含质因子 7
。 习惯上我们把 1 当做是第一个丑数。求按从小到大的顺序的第 n
个丑数
提示:
1
是丑数。n
不超过1690
。
# 测试用例
- 输入:
n = 10
- 输出:
12
- 解释:
1, 2, 3, 4, 5, 6, 8, 9, 10, 12
是前10
个丑数。
# 思路
首先从丑数的定义我们知道,一个丑数的因子只有 2,3,5
,那么丑数 p = 2 ^ x * 3 ^ y * 5 ^ z
换句话说一个丑数一定由另一个丑数乘以 2 或者乘以 3 或者乘以 5 得到
那么我们从 1
开始乘以 2,3,5
,就得到 2,3,5
三个丑数,在从这三个丑数出发乘以 2,3,5
就得到 4,6,10, 6,9,15, 10,15,25
九个丑数
因为这 9
个数可能会有重复的,所以从这 9
个丑数中拿出最小的数(要比丑数数组中的数大)加入丑数数组
(1) 丑数数组 [1]
- 乘以 2:2
- 乘以 3:3
- 乘以 5:5
把 2 放入丑数数组
(2) 丑数数组 [1,2]
- 乘以 2:2 4
- 乘以 3:3 6
- 乘以 5:5 10
把 3 放入丑数数组
# 代码实现
var __readline = require("readline-sync");
__readline.setDefaultOptions({ prompt: "" });
var readline = __readline.prompt;
console.log("请输入n: ");
let n = Number(readline());
/**
* @param {number} n
* @return {number}
*/
var nthUglyNumber = function (n) {
if (n === 0) {
return 0;
}
// 存储丑数的数组 —— 保证从小到大排序
let res = [1];
while (res.length < n) {
// 遍历数组中的元素
// 乘2 —— 得到比此时丑数数组最后一个元素大的值
let n2 = res
.map((item) => item * 2)
.find((item) => item > res[res.length - 1]);
// 乘3 —— 得到比此时丑数数组最后一个元素大的值
let n3 = res
.map((item) => item * 3)
.find((item) => item > res[res.length - 1]);
// 乘5 —— 得到比此时丑数数组最后一个元素大的值
let n5 = res
.map((item) => item * 5)
.find((item) => item > res[res.length - 1]);
// 取三个操作得到的最小值,放入丑数数组
res.push(Math.min(n2, n3, n5));
}
return res[n - 1];
};
const res = nthUglyNumber(n);
console.log("结果为: ", res);
/*
请输入n:
10
结果为: 12
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48