版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/qq_38148754
本人水平有限,同在学习,如若发现问题还请及时批评指正。
问题描述:
找出只含有素因子2,3,5的第n小的数(丑数),认为1也是丑数:
预备知识:最小堆
相信大家都了解最小堆的概念,熟悉堆排序的朋友也一定更容易理解这种数据结构。我在这里简单叙述一下。最小堆首先是一个完全二叉树,其中任一非终端节点的数据值均不大于其左子节点和右子节点的值。最小堆的根节点是整个二叉树中最小的值。本文的解决思路就是依靠最小堆来实现的。
问题分析:
在本题中1是最小的丑数,要找到第n小的丑数,就从1开始,一直找到第n个丑数即是所求。
丑数是只含有素因子2,3,5的数,我们可以用已存在的丑数分别乘2,3,5,得到的数依然满足只含有素因子2,3,5,即依然是丑数。我们先声明一个结果集result_set=[1],初始只包含丑数1,该结果集 result_set 采用最小堆结构来存储。
循环n次,每次从最小堆中取出根节点,即最小值 ,赋给变量result,用result依次与2,3,5相乘得到三个数,若最小堆result_set中不含有该数,则将该数加入到最小堆中,继续循环执行。等到执行到第n次,即第n次弹出堆中的最小值result,该值便是第n小的丑数,即为所求。
特意采用堆结构是因为我们需要尽量按照从小到大的顺序生成丑数以便于寻找第n小的丑数。这就要求每次的result必须是最小的丑数,以使新生成的丑数尽量小。并且第k+1次生成的三个数中可能存在数比第k次生成的数小,这给我们每次都必须挑选出最小的丑数增加了不小困难。而维护一个最小堆结构则解决了这一系列的麻烦,每次只需要取出根节点即可保证我们每次都能得到最小的丑数。
参考代码:
from heapq import heappop, heappush
class Solution: #heappop heappush 分别是弹出根节点和插入数据到堆中 操作
"""
@param n: An integer
@return: the nth prime number as description.
"""
def nthUglyNumber(self, n):
# write your code here
result_set = [1] #初始结果集
factor = [2,3,5] #3个素因子
if n == 1: #如果n=1 直接返回结果 1
return 1
for _ in range(n):
result = heappop(result_set) #取出根节点
for fac in factor: #生成三个丑数
tem = fac * result
if tem not in result_set: #若结果集中不存在该数就加入结果集
heappush(result_set, tem)
return result