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:
迭代器:
for循环可用于任何“可迭代对象”,这其实就是迭代器
Python中的迭代器协议就是有next方法的对象会前进到下一结果,而在一系列结果的末尾是,则会引发StopIteration
迭代工具内部会在每次迭代时调用next方法,并且捕捉StopIteration异常来确定何时离开
使用迭代器一个显而易见的好处就是:每次只从对象中读取一条数据,不会造成内存的过大开销。
生成器:
包含yield语句的函数会被特地编译成生成器。当函数被调用时,他们返回一个生成器对象,这个对象支持迭代器接口
不像一般的函数会生成值后退出,生成器函数在生成值后会自动挂起并暂停他们的执行和状态,他的本地变量将保存状态信息,这些信息在函数恢复时将再度有效
>>> def g(n): ... for iin range(n): ... yield i**2 ... >>> |