LeetCode刷题——超级丑数#313#Medium

超级丑数的思路探讨与源码
    超级丑数的题目如下图,该题属于数组类和数学类型的题目,主要考察对于数组搜索方法的使用和数学方法的理解。本文的题目作者想到2种方法,分别是优先队列方法和动态规划方法,其中优先队列方法使用Java进行编写,而动态规划方法使用Python进行编写,当然这可能不是最优的解法,还希望各位大佬给出更快的算法。
在这里插入图片描述
    本人认为该题目可以使用优先队列方法的思路进行解决,首先初始化一个优先队列,并将队列元素添加最小丑数1,然后开始遍历循环,如果循环完毕就返回结果,否则就开始搜索数组,取出其中最小值,然后将最小值所对应的丑数进行插入队列的操作,最终直到循环结束并返回结果。那么按照这个思路我们的Java代码如下:

#喷火龙与水箭龟
class Solution {
    public int nthSuperUglyNumber(int n, int[] primes) {
        PriorityQueue<Integer> queueList = new PriorityQueue<>();
        queueList.add(1);
        while (n-- > 0) {
            int pollNum = queueList.poll();
            if (n == 0){
                return pollNum;
            }
            for (int jr:primes) {
                if (jr <= Integer.MAX_VALUE / pollNum){
                    queueList.add(jr*pollNum);
                }
                if (pollNum % jr == 0){
                    break;
                }
            }
        }
        return -1;
    }
}

在这里插入图片描述
    显然,我们看到优先队列方法的效果还可以,同时还可以使用动态规划的方法解决。首先计算数组的长度,并初始化动态规划数组,动态规划的数组元素是代表第n+1个丑数,再把动态规划数组的第一个元素设置为1;再初始化一个代表每个质因子现在与哪个丑数相乘的数组。然后开始遍历循环数组,如果当前质因子乘它的丑数小于当前的丑数,就更新当前丑数并更新变化坐标,如果相等就直接进行变化操作。以此循环,直到最终结束并返回结果。所以按照这个思路就可以解决,下面是Python代码:

#喷火龙与水箭龟
class Solution:
    def nthSuperUglyNumber(self, n: int, primes: List[int]) -> int:
        primesLen = len(primes)
        dpArr = [inf] * n
        dpArr[0] = 1
        indArr = [0] * primesLen
        for ir in range(1, n):
            changeFlag = 0
            for jr in range(primesLen):
                if(primes[jr] * dpArr[indArr[jr]] < dpArr[ir]):
                    changeFlag = jr
                    dpArr[ir] = primes[jr] * dpArr[indArr[jr]]
                elif(primes[jr] * dpArr[indArr[jr]] == dpArr[ir]):
                    indArr[jr] = indArr[jr] + 1
            indArr[changeFlag] = indArr[changeFlag] + 1
        return dpArr[-1]

在这里插入图片描述
    从结果来说Java版本的优先队列的效率还可以,而Python版本的动态规划方法的速度也不错,但应该是有更多的方法可以进一步提速的,希望朋友们能够多多指教,非常感谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值