题目263/4:Ugly Number I II
leetcode上题目263、题目264,同时是《offer》上面试题34。
1. 题目263:Ugly Number I
链接:https://leetcode.com/problems/ugly-number/
判断是否是丑数,代码如下:
class Solution {
public:
bool 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;
return num == 1;
}
};
2. 题目264:Ugly Number II
链接:https://leetcode.com/problems/ugly-number-ii/
输出第n个丑数。
思路1:按顺序每个数都判断是否是丑数,这样结果是TLE。
代码1:
class Solution {
public:
bool isUgly(int num) {
while (num % 2 == 0)
num /= 2;
while (num % 3 == 0)
num /= 3;
while (num % 5 == 0)
num /= 5;
return num == 1;
}
int nthUglyNumber(int n) {
int count, res, i;
res = 1;
count = 1;
while (count < n) {
++ res;
if (isUgly(res))
++ count;
}
return res;
}
};
思路2:只生成丑数,其他数不做判断。
丑数也丑得很有特点,丑数都是前面的丑数与2、3、5的乘积。
假设我们现在已经有排序好的N个丑数,现在最大的丑数记为M,求下一个丑数。
求下一个丑数,将已经得到的丑每一个分别乘以2、3、5,乘以2得到第一个大于M的丑数M2,乘以3得到第一个大于M的丑数M3,乘以5得到第一个大于M的丑数M5,取M2、M3、M5这3个数中的最小值就是M之后的下一个丑数。
再分析,还要可以优化的,只需要记录位置,代码如下:
class Solution {
public:
int NthUglyNumber(int n) {
int pos2, pos3, pos5;
vector<int> res(1, 1);
pos2 = 0;
pos3 = 0;
pos5 = 0;
while (res.size() < n) {
int m2 = res[pos2] * 2;
int m3 = res[pos3] * 3;
int m5 = res[pos5] * 5;
int mn = min(m2, min(m3, m5));
if (mn == m2)
++ pos2;
if (mn == m3)
++ pos3;
if (mn == m5)
++ pos5;
res.push_back(mn);
}
return res.back();
}
};
lintcode也有对应的题目,需要多注意一点是,返回类型是long long类型的,如果求第n个丑数,n比较大时,int类型会溢出。