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.
思路
要得到第N个丑陋数,最直接的想法就是从1开始递增循环,直到找到第N个丑陋数,但是这样明显开销太大,而且我们没有用到已经生成的丑陋数的信息。直接在问题一上修改代码就可。
class Solution {
public:
int nthUglyNumber(int n) {
int count = 1;
int number = 0;
while(count <= n){
number++;
if(isUgly(number)){
count++;
}
}
return number;
}
bool isUgly(int num){
if(num<=0){
return false;
}
while(num%2==0) num=num/2;
while(num%3==0) num=num/3;
while(num%5==0) num=num/5;
if(num==1){
return true;
}
else
return false;
}
};
方法二: (感谢原po分享https://segmentfault.com/a/1190000003480992)
我们应该想一个方法,能够顺序的、只生成丑陋数就好了。观察发现,一个丑陋数,一定是某个丑陋数的2、3、5倍,也就是说由他的因子乘以2/3/5得到。但问题在于,小的丑陋数乘5不一定比大的丑陋数乘2要小,我们没法直接使用目前最大的丑陋数来乘2、3、5顺序得到更大的丑陋数。不过,我们可以确定的是,小的丑陋数乘2,肯定小于大的丑陋数乘2。
所以我们使用三个指针,分别记录乘2、3、5得出的目前最大丑陋数,这样我们通过比较这三种最大丑陋数(这里最大是相对于只乘2、只乘3、只乘5三种不同情况下最大的丑陋数),就得到了所有数里最大的丑陋数。
int nthUglyNumber(int n) {
List<Integer> list = new ArrayList<Integer>();
list.add(1);
int p2 = 0, p3 = 0, p5 = 0; //这里是2,3,5的三个指针
while(list.size() < n){
int m2 = list.get(p2) * 2;
int m3 = list.get(p3) * 3;
int m5 = list.get(p5) * 5;
int min = Math.min(m2,Math.min(m3,m5));
list.add(min);
if(min == m2) p2++; //指针移动
if(min == m3) p3++;
if(min == m5) p5++;
}
return list.get(list.size()-1);
}
比如 最开始是list中只有 1 ,那么指针p2,p3,p5都会指向1, 然后经过nthUglyNumber(),list中就会加入2 变成 1 2, 此时指针p3,p5指向1 p2指向2.