【LEETCODE】313-Super Ugly Number [Python]

yield,map,heapq.merge,next
摘要由CSDN通过智能技术生成

Write a program to find the nth super ugly number.

Super ugly numbers are positive numbers whose all prime factors are in the given prime listprimes of size k. For example,[1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32] is the sequence of the first 12 super ugly numbers givenprimes = [2, 7, 13, 19] of size 4.

Note:

(1) 1 is a super ugly number for any givenprimes.

(2) The given numbers in primes are in ascending order.

(3) 0 < k ≤ 100, 0 <n ≤ 106, 0 <primes[i] < 1000.


题意:

写个程序找到第n个 super ugly number

super ugly number 就是一些只包含给定的k个质因子的正数

例如 [1, 2, 4, 7, 8, 13, 14, 16, 19, 26, 28, 32] 就是12 个super ugly number构成的序列,它们由 size 为 4 的质数列表 [2, 7, 13, 19]生成 


注:

1 是super ugly number,无论给定怎样的质数列表

给定的质数列表是升序的

0 < k ≤ 100, 0 < n ≤ 106, 0 < primes[i] < 1000


思路:

就是给的size 为 4 的素数列表 [2, 7, 13, 19] 

初始的super ugly number 是1

由1生成的 2,7,13,19: [1,2,7,13,19:]

继续由2及列表生成 [4,14,26,38]

由7及列表生成[14,49,91,133]

由13及列表生成[。。。]

由19及列表生成[。。。]

。。。

sort:以上生成的数字要保持由小到大的顺序---heapq.merge

duplicate:遇到重复的数字只要一个---if ugly != uglies[-1]

N:只返回第N个上述序列中的数字---while len(uglies) < n



参考:

http://segmentfault.com/a/1190000004187449

http://bookshadow.com/weblog/2015/12/03/leetcode-super-ugly-number/


这些数字是怎么产生的

除了第一个数字,其余所有数字都是之前已有数字乘以任意一个在质数数组里的质数

所以对于每一个已有的数字,我们都可以分别乘以所有在质数数组里的质数得到一系列的数字,这些数字肯定会存在在以后的序列中

由于我们是要得到从小到大的结果,所以我们可以维护个count数组

来记录对于对应质数下一个需要被乘的已有数的index



Python:

import heapq

class Solution(object):
    def nthSuperUglyNumber(self, n, primes):
        """
        :type n: int
        :type primes: List[int]
        :rtype: int
        """
        uglies = [1]
        def gen(prime):
            for ugly in uglies:
                yield ugly * prime
        merged = heapq.merge(*map(gen, primes))
        while len(uglies) < n:
            ugly = next(merged)
            if ugly != uglies[-1]:
                uglies.append(ugly)
        return uglies[-1]
        
n=12
primes=[2,7,13,19]
r=Solution().nthSuperUglyNumber(n, primes)
print (r)


不会的地方:

yield:

关于Python中的yield

迭代器:

for循环可用于任何“可迭代对象”,这其实就是迭代器

Python中的迭代器协议就是有next方法的对象会前进到下一结果,而在一系列结果的末尾是,则会引发StopIteration

迭代工具内部会在每次迭代时调用next方法,并且捕捉StopIteration异常来确定何时离开

使用迭代器一个显而易见的好处就是:每次只从对象中读取一条数据,不会造成内存的过大开销。


生成器:

包含yield语句的函数会被特地编译成生成器。当函数被调用时,他们返回一个生成器对象,这个对象支持迭代器接口

不像一般的函数会生成值后退出,生成器函数在生成值后会自动挂起并暂停他们的执行和状态,他的本地变量将保存状态信息,这些信息在函数恢复时将再度有效


>>> def g(n):

...     for iin range(n):

...             yield i**2

...

>>>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值