剑指offer---丑数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiaohuigou1786/article/details/82533511

题目:把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

解法:我们从上面可以知道丑数的质因子只有2,3,5三个,我们如果要知道从小到大排列的第N个丑数,可以使用暴力破解的方法:即逐个判断1,2,3,4,5,6,7,8,9.........等是不是丑数,直至找到第N个丑数为止,然后返回打印。但是暴力破解的方法的时间复杂度特别高。那么怎么降低时间复杂度呢?

我们先来看一下丑数的构成,即每一个丑数都是之前的丑数*2或者*3或者*5,因此后面的丑数都是之前丑数的倍数。

第一个丑数:1

第二个丑数是之前的丑数【1】*2或*3或*5中最小的那个,即1*2,1*3,1*5中最小的,因此第二个丑数为2.

第二个丑数:2

第三个丑数是之前的丑数【1,2】*2或*3或*5中最小的那个,即1*2,1*3,1*5,2*2,2*3,2*5中比已经保存的丑数大的同时在新产生的丑数中最小的,因此第三个丑数为3.(因为1*2为2,之前保存的丑数中最大的是2,因此不选择这个)

第三个丑数:3

以此类推。。。

第四个丑数:4

。。。。。。。。。

在知道丑数的构成原理以后我们就可以不用暴力穷举到产生N个丑数了,我们可以通过之前的丑数来产生新的丑数,不过我们的代价是需要一个N长的数组保存产生的丑数,从而方便新的丑数的生成,这种方法是空间换时间

知道了原理以后我们的代码就很简单了,代码如下所示:

class Solution:
    def GetUglyNumber_Solution(self, index):#index为N
        # write code here
        if index == 0:
            return 0
        if index == 1:
            return 1
        n = 1
        ugly = [1]
        while n < index:#逐步产生N个丑数
            l_old = []
            for i in ugly:
                for j in [2,3,5]:
                    l_old.append(i*j)#l_old 添加了之前的丑数*2,*3,*5的所有丑数
            cur_max = max(ugly)#之前丑数中最大的丑数,我们新加的丑数必须大于之前已经保存的最大的丑数
            l_new = [x for x in l_old if x > cur_max]
            ugly.append(min(l_new))#把新丑数加入丑数列表
            n += 1
        return ugly[index-1]#因为列表下表是从0开始的,所以第index个的下标是index-1

猜你喜欢

转载自blog.csdn.net/xiaohuigou1786/article/details/82533511