264. Ugly Number II
#难度:medium
#题目:
Write a program to find the n
-th ugly number.
Ugly numbers are positive numbers whose prime factors only include 2, 3, 5
. For example, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12
is the sequence of the first 10
ugly numbers.
Note that 1
is typically treated as an ugly number.
#题目中文意思:
ugly数的意思是这个数的质因数只能是2,3,5
#帮助理解:
最简单理解就是:你的那个数只能被2/3/5整除到1 好像12,12/2=6,6/2=3,3/3=1 所以12是可以的
但是14就不行了, 14/2=7, 7/2有余数 7/3有余数 7/5有余数
所以你就要想一个算法去求 第几位的ugly数 例如他要你求第10个
那么就是 1,2,3,4,5,6,8,9,10,12 12就是第十个ugly了
那么就是 1,2,3,4,5,6,8,9,10,12 12就是第十个ugly了
#难点:
而且不许用循环 所以你不能每一个数都去试试能不能除到1
难点在这里 √
难点在这里 √
#提示:
#题解:
简易版:(多层循环,时间复杂度过大,并不能通过)
prefect版:
int min(int a,int b,int c)
{
int minNum=a>b?b:a;
return c>minNum?minNum:c;
}
class Solution {
public:
int nthUglyNumber(int n) {
int *ugly=new int[1+n];
ugly[0]=1;
if(n<=1)return ugly[0];
int index2,index3,index5;
//[1]
index2=index3=index5=0;
//[2]
int queue2,queue3,queue5;
queue2=2,queue3=3,queue5=5;
int minNum=min(queue2,queue3,queue5);
for(int i=1;i<=n;i++)
//[3]
{
minNum=ugly[i]=min(queue2,queue3,queue5);
if(minNum==queue2){queue2=2*ugly[++index2];}
if(minNum==queue3){queue3=3*ugly[++index3];}
if(minNum==queue5){queue5=5*ugly[++index5];}
}
return ugly[--n];
}
};
|
#题释:
//[1]: 三个队列对应的下标 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//[2]:
三个队列
queue2
queue3
queue5
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
//[3]:
第一次循环:
第二次循环:
第三次循环:
第四次循环:
第五次循环:
第六次循环:
第七次循环:
第八次循环:
网上说得好复杂,理解了很久,然后其实就这意思:
①每次把三个队列中最小的那个数用ugly来储存,这样就能实现了排序的目的
②得知最小的数后,用此队列基本质数去乘上“此队列中还没乘过的ugly数”,怎么理解呢,就 例如第七~八次循环,因为最小的数位queue2和queue3中的6,所以
用2(此队列基本质数) 乘以 queue2 (此队列) 中的 ugly[3] (还没乘过的ugly数,这里是4)
同理,
用3(此队列基本质数) 乘以 queue3 (此队列) 中的 ugly[2] (还没乘过的ugly数,这里是3)
③然后重复循环,找最小赋值给ugly,乘乘乘。
这样做的目的是什么呢:
这样做的话,能确保
1.ugly每次得到的都是三个队列中最小的数,排序√
2.ugly中每个数都用过,不遗漏数√
3.减少循环数,时间复杂度低√
|