python 丑数

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

跟跳台阶的问题很相似,如果想要获得第N个丑数,就必须要一直计算到N个

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

思路一:
    逐步判断每个自然数是不是丑数(这样带来的时间按复杂度很大)
    您的代码已保存
    运行超时:您的程序未能在规定时间内运行结束,请检查是否循环有错或算法复杂度过大。
思路二:
    答案给出的精妙解法:
    假设已知当前的丑数序列为:[1,2,3,4,5]
    则后序填充丑数序列所使用的数值必然出自于对于当前丑数序列中的数值乘以:2,3,5
    只是按照一定顺序排列,故而当前的任务是需要找到有当前丑数列表中的元素所产生的(不再列表中的)最小丑数值
    给定3个指针索引下标:index_2,index_3,index_5,分别表示当前需要乘以相应因子的丑数(在当前的丑数列表中)
    初始情况下:index_2,index_3,index_5 相等,都指向位置position index=0
    对于index_2,从当前的index_2开始遍历列表,找到第一个乘以2能够大于list[-1]的丑数因子,即数值3,index_2=2   可能是下一个丑数的数值为6
    对于index_3,从当前的index_3开始遍历列表,找到第一个乘以3能够大于list[-1]的丑数因子,即数值2,index_2=1   可能是下一个丑数的数值为6
    对于index_5,从当前的index_5开始遍历列表,找到第一个乘以5能够大于list[-1]的丑数因子,即数值2,index_5=1   可能是下一个丑数的数值为10
    而最小的丑数是6,
    更新后的丑数列表[1,2,3,4,5,6] index_2=2  index_2=1  index_5=1
    进行下一次循环
'''
class Solution:
    def is_ulgy(self,num):
        # 判断一个自然数是不是丑数
        # print('here',num)
        while (num % 2 == 0):
            num = num // 2
        while (num % 3 == 0):
            num = num // 3
        while (num % 5 == 0):
            num = num // 5
        if num==1:
            return True
        else:
            return False
    def GetUglyNumber_Solution(self, index):
        # print(index)
        # write code here
        factor = [1, 2, 3, 4, 5]
        if index <= len(factor):
            return factor[index - 1]
        last = index - len(factor)
        start = 5
        # print(last)
        while(last):
            # print(last)
            start=start+1
            # 从小到大遍历自然数,判断每个数值是不是丑数,如果当前的数值是丑数,则last数值减1
            # 从6开始
            # print('here',self.is_ulgy(6))
            while(1):
                if(self.is_ulgy(start)):
                    break
                else:
                    start += 1
            last -= 1
        return start
if __name__=='__main__':
    print(Solution().GetUglyNumber_Solution(1))#1
    print(Solution().GetUglyNumber_Solution(10))# 12
    print(Solution().GetUglyNumber_Solution(400))#311040
    import time
    start=time.time()
    print(Solution().GetUglyNumber_Solution(1500))
    end=time.time()
    print('calculating',end-start)# 非常慢

class Solution:
    def GetUglyNumber_Solution(self, index):
        # write code here
        factor = [1, 2, 3, 4, 5]
        if index==0:
            return 0
        if index <= len(factor):
            return factor[index - 1]
        index_2=0
        index_3=0
        index_5=0
        last=index-len(factor)
        while(last):
            temp=[]
            for can_2 in range(index_2,len(factor)):
                if factor[can_2]*2>factor[-1]:
                    temp.append(factor[can_2]*2)
                    index_2=can_2
                    break
            for can_3 in range(index_3,len(factor)):
                if factor[can_3]*3>factor[-1]:
                    temp.append(factor[can_3]*3)
                    index_3=can_3
                    break
            for can_5 in range(index_5,len(factor)):
                if factor[can_5]*5>factor[-1]:
                    temp.append(factor[can_5]*5)
                    index_5=can_5
                    break
            factor.append(min(temp))
            last-=1
        return factor[-1]
# 对于优化后的代码
if __name__=='__main__':
    print(Solution().GetUglyNumber_Solution(1))#1
    print(Solution().GetUglyNumber_Solution(10))# 12
    print(Solution().GetUglyNumber_Solution(400))#311040
    import time
    start=time.time()
    print(Solution().GetUglyNumber_Solution(1500))
    end=time.time()
    print('calculating',end-start)
    '''
    1
    12
    311040
    859963392
    calculating 0.0060062408447265625
    '''
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值