题目:把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
思路:首先想到的是暴力解法,一个一个的判断是不是丑数,并用一个计数器统计是第几个丑数,但是该算法的时间效率很低,无法通过OJ。
之前的暴力解法之所以效率较低,很大程度上是因为不管一个数是不是丑数,我们都需要对它进行计算。
因此我们可以先列出前几个丑数
1, 2,3, 4, 5,6,8, 9, 10,12,15
我们可以发现丑数应该是前面丑数乘以2,3或者5的结果。我们可以建立一个数组,存储排好序的丑数,每次计算下一个丑数时,在之前丑数的基础上分别乘以2、3或者5,并选出比当前最大丑数大的丑数中,最小的一个,继续存入该数组中,直到找到第index个丑数。
事实上,没必要每次从头开始分别乘以2、3或者5,因为已有的丑数是按顺序存放在数组中的,必然存在一个位置t2上的数,在t2之前的数,乘以2小于已有的最大的丑数,在t2之后的数,乘以2大于已有的丑数,所以我们每次只需要记录下t2的位置,并不断更新即可。对于3和5,也存在同样的t3和t5.
class Solution {
public:
int GetUglyNumber_Solution(int index) {
if (index <= 0) return 0;
vector<int> v;
int t2 = 0, t3 = 0, t5 = 0;
int m2, m3, m5;
int nmax = 1;
v.push_back(1);
while (v.size() < index)
{
for (int i = t2; i < v.size(); ++i)
{
if ((v[i] * 2) > nmax)
{
m2 = v[i] * 2;
t2 = i;
break;
}
}
for (int i = t3; i < v.size(); ++i)
{
if ((v[i] * 3) > nmax)
{
m3 = v[i] * 3;
t3 = i;
break;
}
}
for (int i = t5; i < v.size(); ++i)
{
if ((v[i] * 5) > nmax)
{
m5 = v[i] * 5;
t5 = i;
break;
}
}
nmax = min(m2, min(m3, m5));
v.push_back(nmax);
}
return nmax;
}
};
python的解法:
class Solution:
def GetUglyNumber_Solution(self, index):
if index <= 0:
return 0
t2 = 0
t3 = 0
t5 = 0
nmax = 1
v = [1]
m2 = 0
m3 = 0
m5 = 0
while len(v) < index:
for i in range(t2, len(v)):
if (v[i]*2) > nmax:
m2 = v[i]*2
t2 = i
break
for i in range(t3, len(v)):
if (v[i] * 3) > nmax:
m3 = v[i] * 3
t3 = i
break
for i in range(t5, len(v)):
if (v[i]*5) > nmax:
m5 = v[i]*5
t5 = i
break
nmax = min(m2, m3, m5)
v.append(nmax)
return nmax