原题目:
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
解题思路:
一个丑数的因子只可能在2,3,5中,所以,一个丑数肯定由另一个丑数乘以2,3,5获得,从1开始乘得到2,3,5,再用这三个丑数乘2,3,5得到一个队列:3,6,,10,6,9,15,10,15,25,但是我们发现先这个队列有些数是重复的
所以我们可以维护三个队列,再用一个数组存储丑数:
①数组:1
乘2的队列: 2
乘3的队列: 3
乘5的队列: 5
选出三个队列头中的2加入数组,同时再把最小的乘数乘以2,3,5放入这个队列
②数组:1, 2
乘2的队列: 4
乘3的队列: 3 6
乘5的队列: 5 10
选择三个队列头最小的数3加入丑数数组
依次类推,就可以得到第k个丑数
为什么要分成三个队列呢?因为我们让一个数分别乘2,乘3,乘5,把这三种数都分别开一个队列,这样的话同一个队列中肯定有序,再每次取出最小的丑数,肯定也是有序的,而且不会又重复的数字
具体的实现思路:
不需要真的维护三个队列,分别记录三个索引,分别表示这三个队列的头在哪个位置:
①数组: 1
乘2的队列: |2
乘3的队列: |3
乘5的队列: |5
②数组: 1 2
乘2的队列: 2 |4
乘3的队列: |3 6
乘5的队列: |5 10
③数组: 1 2 3
乘2的队列: 2 4 |6
乘3的队列: 3 |6 9
乘5的队列: |5 10 15
具体代码如下:
int GetUglyNumber_Solution(int index) {
if (index < 7) {
return index;
}
// 三个指针,分别表示2, 3, 5队列的丑数
int pIndex2 = 0, pIndex3 = 0, pIndex5 = 0, uglyNum = 1;
// 维护一个队列
vector<int> arr;
arr.push_back(uglyNum);
int uglyPIndexNum2, uglyPIndexNum3, uglyPIndexNum5;
while (arr.size() < index) {
// 每次选出三个队列头最小的数
uglyPIndexNum2 = arr[pIndex2] * 2;
uglyPIndexNum3 = arr[pIndex3] * 3;
uglyPIndexNum5 = arr[pIndex5] * 5;
uglyNum = min(uglyPIndexNum2, min(uglyPIndexNum3, uglyPIndexNum5));
arr.push_back(uglyNum);
if (uglyNum == uglyPIndexNum2)pIndex2++;
if (uglyNum == uglyPIndexNum3)pIndex3++;
if (uglyNum == uglyPIndexNum5)pIndex5++;
}
return uglyNum;
}
如果遇到重复的,指针会跳过去的