大家好,我是挨打的阿木木,爱好算法的前端摸鱼老。最近会频繁给大家分享我刷算法题过程中的思路和心得。如果你也是想提高逼格的摸鱼老,欢迎关注我,一起学习。
题目
264. 丑数 II
给你一个整数 n ,请你找出并返回第 n 个 丑数 。
丑数 就是只包含质因数 2、3 和/或 5 的正整数。
示例 1:
输入: n = 10
输出: 12
解释: [1, 2, 3, 4, 5, 6, 8, 9, 10, 12] 是由前 10 个丑数组成的序列。
示例 2:
输入: n = 1
输出: 1
解释: 1 通常被视为丑数。
提示:
1 <= n <= 1690
思路
这道题目太简洁了,我先给大家翻译一下题目的意思, 丑数指的是这个数只能由1乘以[2, 3, 5]中的任意一个元素,经过n轮乘法后达到的值。而且需要从小到大排列,我们可以直接用三根指针,指向我们当前的数组,然后分别标识当前指针乘到数组的第几位了,每次存放三根指针对应的最小值进数组即可。然后有个注意点,可能会有重复元素,比如2 * 3 = 3 * 2,这种情况两根指针都需要往后走一位。
举个例子:
p1 => 代表 * 2的指针, p2 => 代表 * 3的指针, p5 => 代表 * 5的指针
第一轮,数组中只有1
[ 1 ] => 三根指针都在索引为0的位置,这时候分别计算他们对应的值, 即 1 * 2, 1 * 3, 1 * 5
然后把最小值推进数组中,同时该指针往后移。
第二轮
[ 1, 2 ] => 第一根表示2的指针在索引1,后两根指针在索引为0的位置,这时候分别计算他们对应的值, 即 2 * 2, 1 * 3, 1 * 5 然后把最小值推进数组中,同时该指针往后移。
第三轮
[ 1, 2, 3 ] => 2 * 2, 2 * 3, 1 * 5
依此类推...
实现
/**
* @param {number} n
* @return {number}
*/
var nthUglyNumber = function(n) {
let p1 = p2 = p3 = 0;
let result = [ 1 ];
while (result.length < n) {
let v1 = result[p1] * 2,
v2 = result[p2] * 3,
v3 = result[p3] * 5;
// 找它们的最小值,就是丑数
let cur = Math.min(...[v1, v2, v3]);
// 可能有重复值,所以不能用else if
if (cur === v1) p1++;
if (cur === v2) p2++;
if (cur === v3) p3++;
result.push(cur);
}
return result[n - 1];
};
看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。