题目描述
把只包含质因子 2 、 3 和 5 2、3和5 2、3和5的数称作丑数( U g l y Ugly Ugly N u m b e r Number Number)。例如 6 、 8 6、8 6、8都是丑数,但 14 14 14不是,因为它包含质因子 7 7 7。 习惯上我们把 1 1 1当做是第一个丑数。求按从小到大的顺序的第 N N N个丑数。
思路:因为丑数只包含 2 , 3 , 5 2,3,5 2,3,5质因子,那么我们要求第 N N N个丑数,即可以从第 1 1 1个丑数开始,接下来的一个丑数必然也只包含 2 , 3 , 5 2,3,5 2,3,5质因子,那么我们只要将第一个丑数乘以 2 , 3 , 5 2,3,5 2,3,5再取最小值即为第二个丑数,那么如何才能得到有序且无重复的丑数序列呢?
我们可以维护三个队列:
(1) 丑数数组:1
乘以2的队列:2,4,6
乘以3的队列:3,6,9
乘以5的队列:5,10,15
(2)丑数数组:1,2 (取三个队列队头的最小值)
乘以2的队列:4,6,8
乘以3的队列:3,6,9
乘以5的队列:5,10,15
(3)丑数数组:1,2,3 (取三个队列队头的最小值)
乘以2的队列:4,6,8
乘以3的队列:6,9,12
乘以5的队列:5,10,15
(4)丑数数组:1,2,3,4 (取三个队列队头的最小值)
乘以2的队列:6,8,10
乘以3的队列:6,9,12
乘以5的队列:5,10,15
(5)丑数数组:1,2 ,3,4,5 (取三个队列队头的最小值)
乘以2的队列:6,8,10
乘以3的队列:6,9,12
乘以5的队列:10,15,20
可以看到,每次都取三个队列队头的最小值进行比较,然后放入数组中,由于三个队列都是排序的,所以挑选出来的数自然也是排序的,当遇到重复的元素时,将该元素所在的队列都出队,这样就可以得到第 N N N个丑数。
实际实现:当然我们实现可以不使用队列,可以采用三个标记 t 2 、 t 3 、 t 5 t2、t3、t5 t2、t3、t5,当挑选了某个队列中的元素时,便将对应的标记 + + ++ ++,达到出队的效果,例如挑选了 2 2 2,则 t 2 + + t2++ t2++,那么下一次再选 2 2 2队列的元素即为 4 4 4(用 a n s [ t 2 ] ∗ 2 ans[t2] * 2 ans[t2]∗2表示乘以2的队列)
class Solution {
public:
int GetUglyNumber_Solution(int index) {
//丑数序列为1,2,3,4,5,6......
if (index < 7)
return index;
vector<int> ans(index);
ans[0] = 1;
int t2 = 0, t3 = 0, t5 = 0;
for (int i = 1; i < index; ++i) {
//从3个队列中选最小值
ans[i] = min(ans[t2] * 2, min(ans[t3] * 3, ans[t5] * 5));
//满足某一队列中的元素则出队
if (ans[t2] * 2 == ans[i]) t2++;
if (ans[t3] * 3 == ans[i]) t3++;
if (ans[t5] * 5 == ans[i]) t5++;
}
return ans[index - 1];
}
};