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的数
那么根据丑陋数的定义,我们将给定数除以2、3、5,直到无法整除,也就是除以2、3、5的余数不再为0时停止
这时如果得到1,说明是所有因子都是2或3或5,如果不是1,则不是丑陋数。
class Solution {
public:
bool isUgly(int num) {
if(num<=0)
return false;
if(num==1)
return true;
while(num>=2 && num%2==0) //先将因子2除完,接着3,5
num/=2;
while(num>=3 && num%3==0)
num/=3;
while(num>=5 && num%5==0)
num/=5;
return num==1;
}
};
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.
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.Show More Hint
提示说的很清楚,第n个丑数的沿途大量的数都不是丑数,为了能跳过对他们的判断
直接由小到大生成丑数进行统计个数,直到是第n个为止
用三个临时数和数组来渐进增大丑数。
本质上下面这种解法是动态规划,显然第n个丑数肯定是由前面某个丑数乘以2或者3或者5,
问题就在于生成的丑数要是有序的!这可就麻烦了,三个指针总是维护*2*3*5的结果,他们总是下一个候选丑数!
令figure2是由某个较小丑数*2产生的新丑数,
令figure3是由某个较小丑数*3产生的新丑数,
令figure5是由某个较小丑数*5产生的新丑数,
则第n个丑数肯定是三者中的较小者,但是必须得保证我们三者的生成规则。
三者的生成规则:
显然下一次的figure2,figure3,figure5必须比当前产生的丑数大,
那么就要求一旦当前产生的丑数大比三个候选丑数大就将其变大一点,从小到大沿途乘以2/3/5(具体看代码)
以下设计参考别人:
//首先思路:提示说的很清楚,第n个丑数的沿途大量的数都不是丑数,为了能跳过对他们的判断
//直接由小到大生成丑数进行统计个数,直到是第n个为止
//用三个临时数来渐进增大的丑数
class Solution {
public:
int nthUglyNumber(int n)
{
vector<int> ugly(n,0);
ugly[0]=1;
int figure2=2,figure3=3,figure5=5;
int index2=0,index3=0,index5=0;
for(int i=1;i<n;++i)
{
ugly[i]=min(figure2,min(figure3,figure5));//根据数列得到最小的值
if(figure2<=ugly[i])
figure2=2*ugly[++index2];
if(figure3<=ugly[i])
figure3=3*ugly[++index3];
if(figure5<=ugly[i])
figure5=5*ugly[++index5];
}
return ugly[n-1];
}
};
其他小伙伴的做法:
所有的ugly number都是由1开始,渐乘2/3/5一步一步生成。
只要将这些生成的数排序即可获得,自动排序可以使用set集
这样每次取出的第一个元素就是最小元素,由此再继续生成新的ugly number.
这样做有一个弊端,每次插入都有O(lg(N))的时间复杂度,所以比上一种方法慢。
class Solution {
public:
int nthUglyNumber(int n) {
set<long long> order;//最小堆(顶是最小值)允许重复数据存在,不能使用堆
order.insert(1);
int count = 0;
long long curmin = 0;
while(count < n)
{
curmin = *(order.begin());
order.erase(order.begin());
order.insert(curmin * 2);
order.insert(curmin * 3);
order.insert(curmin * 5);
count ++;
}
return (int)curmin;
}
};
Write a program to find the nth super ugly number.
Super ugly numbers are positive numbers whose all prime factors are in the given prime list primes
of size k
. For example, [1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32]
is the sequence of the first 12 super ugly numbers given primes
= [2, 7, 13, 19]
of size 4.
Note:
(1) 1
is a super ugly number for any given primes
.
(2) The given numbers in primes
are in ascending order.
(3) 0 < k
≤ 100, 0 < n
≤ 106, 0 < primes[i]
< 1000.
分析:
方法和上面一题一样,只不过因子多了几个而已,变量都取得一样,就不多解释了!
class Solution {
public:
int nthSuperUglyNumber(int n, vector<int>& primes) {
vector<int> ugly(n,0);
vector<int> figures(primes);
vector<int> indexs(n,0);
ugly[0]=1;
for(int i=1;i<n;i++)
{
ugly[i]=figures[0];
for(int j=1;j<primes.size();j++)
ugly[i]=min(ugly[i],figures[j]);
for(int j=0;j<primes.size();j++)
if(figures[j]<=ugly[i])
figures[j]=ugly[++indexs[j]]*primes[j];
}
return ugly[n-1];
}
};
参考资源:
【1】网友,tyq101010,原文地址, http://blog.youkuaiyun.com/tyq101010/article/details/49256889
注:本博文为EbowTang原创,后续可能继续更新本文。如果转载,请务必复制本条信息!
原文地址:http://blog.youkuaiyun.com/ebowtang/article/details/51581228
原作者博客:http://blog.youkuaiyun.com/ebowtang
本博客LeetCode题解索引:http://blog.youkuaiyun.com/ebowtang/article/details/50668895