1.ugly number (I,II,super)
(1)ugly number
链接:http://www.lintcode.com/zh-cn/problem/ugly-number/
写一个程序来检测一个整数是不是丑数
。
丑数的定义是,只包含质因子 2, 3, 5
的正整数。比如 6, 8 就是丑数,但是 14不是丑数以为他包含了质因子 7。
注意事项
可以认为 1
是一个特殊的丑数。
这是一个容易题,应该比较容易想出来,话不多说,直接看代码。
class Solution {
public:
/**
* @param num an integer
* @return true if num is an ugly number or false
*/
bool isUgly(int num) {
// Write your code here
//if(num==1)
// return true;
while(num>1)
{
if(num%5==0)
{
num=num/5;
}
else if(num%3==0)
num/=3;
else if(num%2==0)
num/=2;
else
break;
}
return num==1;
}
};
(2)ugly number ii
链接:http://www.lintcode.com/zh-cn/problem/ugly-number-ii/
设计一个算法,找出只含素因子2
,3
,5
的第 n 大的数。
符合条件的数如:1, 2,3, 4, 5, 6, 8, 9, 10, 12...
注意事项
我们可以认为1
也是一个丑数
分析:中等题,是ugly number题的升级版,只需要把前n个ugly number找出来就可以了,用一个长度为n的vector记录所有丑数,定义3个值变量和3个序号次数变量。每次在前一个丑数的基础上乘以2 or 3或者5,并分别记录值,选择最小那个作为当前值,判断选中哪一个值,将相应的次数加1。返回最后一个值即可。我们知道丑陋数序列可以拆分为下面3个子列表:
(1) 1×2, 2×2, 3×2,4×2, 5×2, …
(2) 1×3, 2×3, 3×3, 4×3, 5×3, …
(3) 1×5, 2×5, 3×5, 4×5, 5×5, …
仔细观察上述三个列表,我们可以发现每个子列表都是一个丑陋数分别乘以2,3,5,而要求的丑陋数就是从已经生成的序列中取出来的,我们每次都从三个列表中取出当前最小的那个加入序列
class Solution {
public:
/*
* @param n an integer
* @return the nth prime number as description.
*/
int nthUglyNumber(int n) {
// write your code here
/*
//方案一
vector<int> f(n,0);
int a=2,b=3,c=5;
f[0]=1;
int index2=0,index3=0,index5=0;
for(int i=1;i<n;i++)
{
f[i]=min(min(a,b),c);
if(a==f[i])
a=2*f[++index2];
if(b==f[i])
b=3*f[++index3];
if(c==f[i])
c=5*f[++index5];
}
return f[n-1];
*/
//方案二
vector<int> ret(n,1);
int i2=0,i3=0,i5=0;
int m2=0,m3=0,m5=0;
for(int i=1;i<n;++i)
{
m2=ret[i2]*2;
m3=ret[i3]*3;
m5=ret[i5]*5;
ret[i]=min(m2,min(m3,m5));
if(ret[i]==m2)
++i2;
if(ret[i]==m3)
++i3;
if(ret[i]==m5)
++i5;
}
return ret[n-1];
}
};
(3)super ugly number
链接:http://www.lintcode.com/zh-cn/problem/super-ugly-number/
写一个程序来找第 n 个超级丑数。
超级丑数的定义是正整数并且所有的质数因子都在所给定的一个大小为 k 的质数集合内。
比如给你 4 个质数的集合 [2, 7, 13, 19]
,那么 [1, 2, 4, 7, 8, 13, 14, 16, 19, 26,28, 32]
是前 12 个超级丑数。
注意事项
1
永远都是超级丑数不管给的质数集合是什么。- 给你的质数集合已经按照升序排列。
- 0 < k ≤ 100, 0 < n ≤ 10^6, 0 < primes[i] < 1000
分析:中等题,是ugly number ii的升级版。质数集合是任意给定的集合,不再只是2,3,5这三个数了。思路和(2)是一样的。根据集合的大小用一个数组来记录某个数次数变量。
直接看代码:
class Solution {
public:
/**
* @param n a positive integer
* @param primes the given prime list
* @return the nth super ugly number
*/
int nthSuperUglyNumber(int n,vector<int>& primes) {
// Write your code here
vector<int> dp(n,INT_MAX);
int len=primes.size();
vector<int> idx(len,0);
dp[0]=1;
for(int i=1;i<n;++i)
{
//dp[i]=INT_MAX;
for(int j=0;j<len;++j)
{
dp[i]=min(dp[i],dp[idx[j]]*primes[j]);
}
for(int j=0;j<len;++j)
{
if(dp[i]==dp[idx[j]]*primes[j])
++idx[j];
}
}
return dp[n-1];
}
};