4. 丑数 II
中文English
设计一个算法,找出只含素因子2,3,5 的第 n 小的数。
符合条件的数如:1, 2, 3, 4, 5, 6, 8, 9, 10, 12...
样例
样例 1:
输入:9
输出:10
样例 2:
输入:1
输出:1
挑战
要求时间复杂度为 O(nlogn) 或者 O(n)。
注意事项
我们可以认为 1 也是一个丑数。
这是领扣上面的第四道题目:
第一种解法,用暴力法,这种逻辑上比较容易,但需要耗费大量的时间和空间,在这里不讲解。
第二种方法:分析法,这个方法也是我在网上找的,借鉴了别人的做法,在这里主要讲一下我自己对这道题目的理解。
从题目给出的符合条件的数中可以得到一个信息,就是所有的数的因数只能为1,2,3,5。排在最后的一个数肯定为数列中某个数的2倍,3倍,5倍。这里我们设置3个索引,命名为index2,index3,index5,初始值全部为0,定义一个数组s,最开始只含有一个元素s[0]=1。这样,我们就有了一个基础的数值。下面我们来进行推算
第一轮:2*s[index2],3*s[index3],5*s[index5] 相当于:2*s[0](值为2),3*s[0](值为3),5*s[0](值为5)
选择最小的数值2,然后index2+1=1 s=[1,2]
第二轮:2*s[index2],3*s[index3],5*s[index5] 相当于:2*s[1](值为4),3*s[0](值为3),5*s[0](值为5)
选择最小的数值3,然后index3+1=1 s=[1,2,3]
第三轮:2*s[index2],3*s[index3],5*s[index5] 相当于:2*s[1](值为4),3*s[1](值为3),5*s[0](值为5)
选择最小的数值2,然后index2+1=2 s=[1,2,3,4]
第四轮:2*s[index2],3*s[index3],5*s[index5] 相当于:2*s[2](值为6),3*s[1](值为6),5*s[0](值为5)
选择最小的数值5,然后index5+1=1 s=[1,2,3,4,5]
第五轮:2*s[index2],3*s[index3],5*s[index5] 相当于:2*s[2](值为6),3*s[1](值为6),5*s[1](值为10)
选择最小的数值6,然后index2+1=3 index3+1=2 s=[1,2,3,4,5,6]
注意:这里index2和index3都加1是因为两个的值都为6,如果只有index2加1,下一轮计算的时候,3*s[index3]还是6,
那么整个s数列中将会出现2个6
第六轮:2*s[index2],3*s[index3],5*s[index5] 相当于:2*s[3](值为8),3*s[2](值为9),5*s[1](值为10)
选择最小的数值8,然后index2+1=4 index3+1=2 s=[1,2,3,4,5,6,8]
按照上面的方法,用代码将他实现即可
class Solution:
def nthUglyNumber(n):
# write your code here
if n<7:
return n
s = [1]
index2 = 0
index3 = 0
index5 = 0
while True:
num = min(2 * s[index2], 3 * s[index3], 5 * s[index5])
if num == 2 * s[index2]:
index2 += 1
if num == 3 * s[index3]:
index3 += 1
if num == 5 * s[index5]:
index5 += 1
s.append(num)
if len(s) == n:
return num