您的位置:首页 > 其它

leetcode解题笔记:Ugly Number I & II

2016-11-20 12:43 267 查看
263.Ugly Number I

Write a program to check whether a given number is an ugly number.

Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. For example, 6, 8 are ugly while 14 is not ugly since it includes another prime factor 7.

Note that 1 is typically treated as an ugly number.

丑数就是只包含因子2,3,5的数。

要判断一个数是不是丑数很简单:比如60 = 2 * 2 * 3 * 5,也就是说:

如果一个数能整除2,就把它连续除以2

如果一个数能整除3,就把它连续除以3

如果一个数能整除5,就把它连续除以5

如果最后得到的数为1,说明这个数只含有2,3或5这三个因子中的一个或多个,那么它就是一个丑数。

public class Solution {
public boolean isUgly(int num) {
if(num == 0) return false;
while(num%2 == 0){
num /=2;
}
while(num%3 == 0){
num /=3;
}
while(num%5 == 0){
num /=5;
}
if(num == 1) return true;
return false;
}

}


264.Ugly Number II

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个丑数,最自然的想法就是利用Ugly Number I 的想法,从1开始判断每个数是不是丑数,直到找到第n个丑数。这样的话,不管一个数是不是丑数我们都要对其进行计算。

Hint:

The naive approach is to call isUgly for every number until you reach the nth one. Most numbers are not ugly. Try to focus your effort on generating only the ugly ones.

An ugly number must be multiplied by either 2, 3, or 5 from a smaller ugly number.

The key is how to maintain the order of the ugly numbers. Try a similar approach of merging from three sorted lists: L1, L2, and L3.

Assume you have Uk, the kth ugly number. Then Uk+1 must be Min(L1 * 2, L2 * 3, L3 * 5).

题目中也给出了一系列提示:

一个丑数肯定是另一个较小的丑数乘以2,3或5的结果

关键是怎么保证数组里的丑数都是排好序的。

可以这么考虑,肯定有这么一个丑数U2,它之前的丑数乘以2都比当前的丑数小,U2是乘以2比当前的丑数大的丑数中最小的一个。同理,也有这样一个U3、U5.

因此,我们只要实时更新 U2,U3,U5这三个丑数,下一个丑数肯定是U2* 2,U3* 3,U5* 5 中最小的那个。

…U5…U2 …U3………M…

这是一个示意图,也就是说,比如我们现在决定了U2* 2是下一个丑数,那么我们就把U2指向U2的下一个丑数。同时,如果当前U3* 3或U5* 5也比当前丑数小的话,也把 U3指向U3的下一个丑数,或U5指向U5的下一个丑数。

public class Solution {
public int nthUglyNumber(int n) {
if(n <= 0) return 0;
int[] ugly = new int
;
ugly[0] = 1;
//维护u2,u3,u5这三个指针,指向丑数数组中的某个丑数
int ugly2 = 0,ugly3 = 0,ugly5 = 0;
//下一个丑数的位置
int index = 1;
while(index < n){
//找出 U2* 2,U3* 3,U5* 5 中最小的那个
int min = Math.min(Math.min(ugly[ugly2]*2,ugly[ugly3]*3),ugly[ugly5]*5);
//令下一个丑数等于这三个值中最小的那个
ugly[index] = min;
//去更新u2,u3,u5这三个指针
while(ugly[ugly2]*2 <= ugly[index]){
ugly2++;
}
while(ugly[ugly3]*3 <= ugly[index]){
ugly3++;
}
while(ugly[ugly5]*5 <= ugly[index]){
ugly5++;
}
index++;

}
return ugly[n-1];

}
}


和传统想法比,这种思路不需要再非丑数的整数上做任何运算,因此效率有明显提升。

但是,这种思路由于需要保存已经生成的丑数,因此需要一个空间为n的数组,等于说用空间消耗换取了时间效率。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode