【leetcode】丑数集合(263、264、313——动态规划)

题目说明:1是丑数 


暴力解法:

num反复除2,3,5直到不能整除。最终判断剩余的数字是否为1,如果是1则为丑数,否则不是丑数。

类似求质数的解法:link

每一个丑数必然是之前丑数与2,3或5的乘积得到的,这样下一个丑数就是用之前的丑数分别乘以2,3,5。

详细算法步骤: 
(1)从第一个丑数1开始,求出1*2=2 ,1*3=3 ,1*5 = 5。 
(2)取上面乘积中大于1的最小值2( 即 min(2,3,5)),作为第二个丑数(丑数是个递增序列。所以第i+1个丑数一定比第i个丑数大) 
(3)求丑数2之前的丑数与2、3、5的乘积:1*2=2 ,1*3=3 ,1*5 = 5; 2*2 = 4; 2*3 = 6。 2*5 =10。 
(4)取上面乘积中大于2的最小值3,作为第三个丑数


(i)取出丑数i之前的丑数分别与2、3、5的乘积

(i+1)取乘积中大于i的最小值作为丑数

(i+2)反复(i)(i+1)的步骤直到计数器等于N

def isUgly(self, num):
    """
    :type num: int
    :rtype: bool
    """
    # 暴力
    while num>1:
        if num%2==0:
            num = num//2
        elif num%3==0:
            num = num//3
        elif num%5==0:
            num = num//5
        else:
            break
    if num==1:
        return True
    else:
        return False

(*^▽^*) 简化

def isUgly(self, num):
    """
    :type num: int
    :rtype: bool
    """
    if num <= 0:
        return False
    for x in [2, 3, 5]:
        while num % x == 0:
            num = num / x
    return num == 1

# 找出第 n 个丑数
class Solution:
    def nthUglyNumber(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n <= 0:
            return False
        t1 = 0
        t2 = 0
        t3 = 0
        res = [1]
        while len(res) < n:
            # 长度可以代表第几个
            res.append(min(res[t1]*2, res[t2]*3, res[t3]*5))
            print(res)
            if res[-1] == res[t1]*2:
                t1 += 1 # t1代表2所产生的丑数到第几步了
            if res[-1] == res[t2]*3:
                t2 += 1
            if res[-1] == res[t3]*5:
                t3 += 1
        return res[-1]

# 和264的区别在于,264是给定primes的个数,求第n个丑数
# 本题事先不知道primes的个数,所以t1,t2,...tn无法确定。

class Solution:
    def nthSuperUglyNumber(self, n, primes):
        """
        :type n: int
        :type primes: List[int]
        :rtype: int
        """
        dp = [1] # res=[]

        lenPrimes = len(primes)
        idxPrimes = [0] * lenPrimes # 类似于t1,t2,t3记录位置
        # print(idxPrimes) # [0, 0, 0, 0]
        counter = 1
        while counter < n:
            min = pow(2, 32)
            for i in range(0, lenPrimes):
                # 找出最小值
                temp = dp[idxPrimes[i]] * primes[i]
                # 求最小的值
                if temp < min:
                    min = temp

            for i in range(0, lenPrimes):
                # 更新最小值所在的位置,类似t1+=1
                # === if res[-1] == res[t1]*2:
                if min == dp[idxPrimes[i]] * primes[i]:
                    idxPrimes[i] += 1
            print(idxPrimes)
            # res.append(min(res[t1]*2, res[t2]*3, res[t3]*5))
            dp.append(min)
            counter += 1
        # print(counter-1) # 11
        # print(len(dp))# 12
        return dp[counter - 1]

 

回去看视频啦!~! (~ ̄▽ ̄)~ 


学了dp再来重新看这个问题。。。

首先给定一个解题基本思路: 

假设M为丑数,M_{1} = 2 * M, M_{2} = 3*M, M_{3} = 5* M则可以认为M_{1}, M_{2}, M_{3} 皆为丑数。

并且下一丑数最小值一定为M_{2}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值