丑数相关问题

此题说明了:

  • 可以尝试用空间换取时间
  • 像丑数这种越来越稀疏的问题,越到后面越体现出算法优化的重要性

《剑指offer34题》只包含因子2、3、5的数叫丑数,找出前1500个丑数。
1.暴力解法
逐一判断是否是丑数


def is_ugly_num(num):
    while num % 2 == 0:
        num //= 2

    while num % 3 == 0:
        num //= 3

    while num % 5 == 0:
        num //= 5

    if num == 1:
        return True
    else:
        return False

@timing
def get_ugly_num2(index = 1500):

    i = 0
    num = 2
    while i < index:
        while not is_ugly_num(num):
            num += 1
        # print(num)
        i += 1
        num += 1

但是如果你知道第1500个丑数是1412006979354108748474554421102313931675676955925788762341700965431346915180599249952936960497614998485448932749141998289061648432939195473813276544243473053215398045741358060286316036246351763861878679739417265182867456的话,您估计也不会用这种方法,丑数的增长几乎的指数型的。丑数500个以后越来越稀疏,暴力破解每找一个都要s级的时间,越来越慢。
500个之前的差别:
get_ugly_num function took 0.002 s
get_ugly_num2 function took 3.665 s

2.正向求解的方法,秒解,暴力破解几分钟还是没有完,我等不及了
面试题之丑数的C++实现求解(孤陋寡闻了,才知道丑数这么high的东东)

@timing
def get_ugly_num(index = 1500):
    if index < 1:
        return

    ugly_list = [1]
    current_ugly_index = 0
    index_2 = 0
    index_3 = 0
    index_5 = 0
    num_2 = 1
    num_3 = 1
    num_5 = 1
    while current_ugly_index < index :

        while num_2 <= ugly_list[current_ugly_index]:
            index_2 += 1
            num_2 *= 2

        while num_3 <= ugly_list[current_ugly_index]:
            index_3 += 1
            num_3 *= 3

        while num_5 <= ugly_list[current_ugly_index]:
            index_5 += 1
            num_5 *= 5

        min_num = min((num_2,num_3,num_5))
        ugly_list.append(min_num)
        current_ugly_index += 1
        # print(min_num)

推荐阅读更多精彩内容