2020.3.10五木开始了CSDN博客之旅
第一次开始学习用MarkDown编辑器写博客,第一感觉是怎么落入了Web前端开发的感觉!
第一篇博客就随意记录一下今天的算法编程题
求按从小到大的顺序第N个丑数
题目描述
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数
C++代码块
class Solution {
public:
int GetUglyNumber_Solution(int index) {
if(index < 7) return index;
//p2,p3,p5分别为三个队列的指针,newNum为从队列头选出来的最小数
int p2 = 0, p3 = 0, p5 = 0, newNum = 1;
queue<int> a;//存放每次乘2得到的丑数的队列
queue<int> b;//存放每次乘3得到的丑数队列
queue<int> c;//存放每次乘5得到的丑数队列
vector<int> v;
while(v.size()!=index){
if(v.size()==0){
v.push_back(newNum);
a.push(newNum*2);
b.push(newNum*3);
c.push(newNum*5);
;
}
else{
int minnum=min(min(a.front(),b.front()),min(a.front(),c.front()));
if(a.front()==minnum) {
a.pop();
}
if(b.front()==minnum){
b.pop();
}
if(c.front()==minnum){
c.pop();
}
v.push_back(minnum);
a.push(minnum*2);
b.push(minnum*3);
c.push(minnum*5);
}
}
return v[v.size()-1];
}
};
算法思想
由于丑数只能是质因子含2、3、5的质因子,所以我们可以理解为每一个丑数都是由某一个较小的丑数乘未知个2或者3或者5得到的。所以本题可以采用模拟法,从1开始从小到大模拟生成丑数,直到生成的轮次等于N,此时生成的丑数即为第N个丑数。
模拟采用三个队列a、b、c和一个存放丑数的数组v。每生成一个新丑数后,用其分别乘2、3、5放入a、b、c 中。并把这个新生成的丑数放入丑数数组v。
那么如何生成新丑数?通过每次弹出三个队列中队首元素的最小值,这个最小值即为新生成的丑数。如果这个最小值属于多个队列,那么就都弹出。
通过以上过程,可以得出两个结论。1.同一个队列中的元素按从小到大排列并且没有重复。2.在丑数数组中,新生成加入的丑数必然大于已经存放于丑数数组的元素,且必然不会有重复生成的丑数。当生成N次丑数时,此时的丑数即为所求。
例如:生成1放入丑数数组,将
1
∗
2
1*2
1∗2放入a,
1
∗
3
1*3
1∗3放入b,
1
∗
5
1*5
1∗5放入c。然后开始生成第二个丑数:此时a、b、c三个队列队首元素最小的为a队首2,所以弹出2放入丑数数组v。同时,将
2
∗
2
2*2
2∗2,
2
∗
3
2*3
2∗3,
2
∗
5
2*5
2∗5加入丑数队列。然后开始第3个丑数生成:此时a中元素为4,b中为3,6,c中为5,10,所以弹出3放入丑数数组中。依此类推。
ps:
尽管很简单,但写完了我的第一个CSDN博客还是有点小兴奋哈哈