丑数
把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
思路
- 队列与数组
根据丑数的性质,可以得出丑数的计算公式:
u g l y = 2 x ∗ 3 y ∗ 5 z ugly = 2^x*3^y*5^z ugly=2x∗3y∗5z
因此,(x,y,z)的任意组合,可以得到丑数。问题就转化为如何得到有序的丑数列表,当列表长度满足要求时,列表的尾元素就是需要求的第N个丑数。
如图,前5个丑数是【1,2,3,4,5】,来思考一下如何通过丑数公式得到该丑数列表。假设ugly是目前最大的丑数1,因为12,13,15中,最小的是2,所以丑数列表为【1,2】,接下来判断22,13,15中最小的丑数,更新丑数列表为【1,2,3】,接下来判断22,32,1*5中最小的丑数,更新列表为【1,2,3,4】,依次类推。
结合下面的两张图可以发现,存在三个队列,每轮比较的都是队首元素,最小的丑数对应的队首指针后移一位。
代码
# -*- coding:utf-8 -*-
class Solution:
def GetUglyNumber_Solution(self, index):
# write code here
if index < 7:
return index
uglyList = [1]
p2,p3,p5 = 0,0,0 #维护三个队列
while len(uglyList) < index: #uglyList中存放排好序的丑数,丑数的生成按照2^p2*3^p3+5^p5
ugly = min(uglyList[p2]*2,uglyList[p3]*3,uglyList[p5]*5)
p2 = p2 + 1 if ugly == uglyList[p2]*2 else p2
p3 = p3 + 1 if ugly == uglyList[p3]*3 else p3
p5 = p5 + 1 if ugly == uglyList[p5]*5 else p5
uglyList.append(ugly)
return uglyList[-1]
- 代码2
# -*- coding:utf-8 -*-
class Solution:
def GetUglyNumber_Solution(self, index):
# write code here
if index < 7:
return index
i, ugly_list = 1, [1]
p2, p3, p5 = 0, 0, 0
q2, q3, q5 = [2], [3], [5]
while i < index:
base = min(q2[p2], q3[p3], q5[p5])
ugly_list.append(base)
if base == q2[p2]:
p2 += 1
if base == q3[p3]:
p3 += 1
if base == q5[p5]:
p5 += 1
q2.append(base*2)
q3.append(base*3)
q5.append(base*5)
i += 1
return ugly_list[index-1]