Python刷OJ———UVa :136 Ugly Numbers

题干:

Ugly numbers are numbers whose only prime factors are 2, 3 or 5. The sequence
1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, …
shows the first 11 ugly numbers. By convention, 1 is included.
Write a program to find and print the 1500’th ugly number.
Input
There is no input to this program.
Output
Output should consist of a single line as shown below, with ‘’ replaced by the number
computed.
Sample Output
The 1500’th ugly number is < number >.
————————————————————————————————————————————
丑数,定义为其质因子只有2, 3 ,5 的非负整数,现在要求写一个程序输出第1500个丑数

思路

(1)质因子只有2, 3, 5 ,也就是说,后面的每一个丑数们都是由前面已经出现的某个丑数乘以2, 3, 5,得到的。由于顺序性的要求,我们要找到大于每一个已有的丑数,并且是最小的新丑数。

(2)方法:先用2乘以前面已经出现的每一个数,直到找到一个大于最后一个数的新丑数,然后先保留这个数。接着再用3, 5进行同样的操作,这样最终我们会得到三个数。然后再选出其中最小的,这即是下一个丑数。

(3)上述操作封装在一个函数中,调用1500次,输出即可

先上代码,下面有对代码的详细解释

list_ugly = [1, 2, 3, 4, 5, 6, 8, 9, 10, 12]


def q_find(list_3, theta_1):
    mid = int(len(list_3) / 2)
    if list_3[mid] <= theta_1:
        if list_3[mid] == theta_1 or list_3[mid + 1] > theta_1:
            return list_3[mid + 1]
        else:
            list_4 = list_3[mid + 1:]
            return q_find(list_4, theta_1)
    if list_3[mid] > theta_1:
        if list_3[mid - 1] <= theta_1:
            return list_3[mid]
        else:
            list_5 = list_3[:mid]
            return q_find(list_5, theta_1)


def multiplication(n):
    theta = list_ugly[len(list_ugly) - 1]
    x = lambda i: i * n
    list_k = list(map(x, list_ugly))
    return q_find(list_k, theta)


def find_next():
    number = list(map(multiplication, [2, 3, 5]))
    return min(number)


def Ugly_1500():
    while len(list_ugly) < 1500:
        _next = find_next()
        list_ugly.append(_next)
    return "The 1500'th ugly number is {}.".format(list_ugly.pop())


print(Ugly_1500())



代码逻辑

:Ugly_1500()将会循环执行find_next()1500次,在find_next()下,map将会抛出三个线程(multiplication),分别去寻找那三个候选数(q_find),然后find_next()会返回最小的一个,并将之添加到列表尾部。

注意点:

(1)如何寻找大于最后一个数的丑数:
这里不妨使用二分查找,但找的是“位置”。假设原丑数序列最后一个丑数是x, 因为该丑数序列是有大小顺序的(乘以2, 3, 5以后的序列也是如此),所以只要找到一个位置,使得前一个数小于等于x,后一个数大于x,则后一个数就是我们要找的数。

(2)但是这里要注意一点,因为我们要尽量使得二分查找的递归函数简单化,减少特殊情况的分支,而且此题只要输出不需要输入。于是我们可以充分利用题目给的初始条件,让初始列表中的数多一些。
这样一来,因为最大的乘以的数是5,所以序列第一个数最大是5,所以如此就能保证一定能在序列中找到我们想要的位置,而不会出现一直递归到头也找不到,这样我们的递归函数只要针对理想情况写就好了。

发布了28 篇原创文章 · 获赞 74 · 访问量 1646

猜你喜欢

转载自blog.csdn.net/CxsGhost/article/details/103993524
今日推荐