Leetcode 313. Super Ugly Number

简介: 题目翻译成中文是『超级丑数』,啥叫丑数?丑数就是素因子只有2,3,5的数,7 14 21不是丑数,因为他们都有7这个素数。 这里的超级丑数只是对丑数的一个扩展,超级丑数的素因子不再仅限于2 3 5,而是由题目给定一个素数数组。与朴素丑数算法相比,只是将素因子变了而已,解法还是和朴素丑数一致的。

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 list primes 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 given primes = [2, 7, 13, 19] of size 4.


原题链接:Super Ugly Number


 题目翻译成中文是『超级丑数』,啥叫丑数?丑数就是素因子只有2,3,5的数,7 14 21不是丑数,因为他们都有7这个素数。 这里的超级丑数只是对丑数的一个扩展,超级丑数的素因子不再仅限于2 3 5,而是由题目给定一个素数数组。与朴素丑数算法相比,只是将素因子变了而已,解法还是和朴素丑数一致的。

 之前我说过,凡是任何编程问题都有暴力的解法,此题也一样,大不了对每个数求其所有素因子,然后再判断改素因子是否在给定的数组中,n个数求素因子的算法时间复杂度就是O(n^2)了,何况第n个超级丑数会远大于n,所以凡事不要老想着暴力解决,最好动动脑子。

 我们先来看看丑数数组存在的一个性质,假设我们已经有了一个丑数数组uglys[n],该数组从小到大保存了所有的丑数。你们绝对存在一个x,使得uglys[x]乘以2或3或5等于uglys[i],且x< i。 通俗易懂的解释就是,第i个丑数就是前面i-1个丑数中的某个丑数乘以2 3或5得到的。这条性质成立就是因为丑数的定义是他除了2 3 5没有其他素因子,而非素因子肯定都可以转化为几个素数相乘。 推而广之,这条性质在超级丑数中也成立,理解了这条性质代码也就很好写了。 我们可以通过已知的丑数乘以2 3或5来获得下一个未知的丑数,但未了保证有序,我们每次只取最小的一个。代码如下。

public class Solution {
    public int nthSuperUglyNumber(int n, int[] primes) {
        int k = primes.length;
        int[] uglys = new int[n];
        int[] p = new int[k];
        uglys[0] = 1;
        for (int i = 1; i < n; i++) {
            for (int j = 0; j < k; j++) {
                while (primes[j] * uglys[p[j]] <= uglys[i-i]) {
                    p[j]++;
                }
            }
            uglys[i] = Integer.MAX_VALUE;
            for (int j = 0; j < k; j++) {
                if (primes[j] * uglys[p[j]] > uglys[i - 1]) {
                    uglys[i] = Math.min(primes[j] * uglys[p[j]], uglys[i]);
                }
            }
        }
        return uglys[n-1];
    }
    public static void main(String[] args) {
        Solution s = new Solution();
        int[] primes = {2, 7, 13, 19, 23, 19, 31, 37, 41, 47, 51, 53, 57, 59, 61, 67, 69, 71, 73};
        System.out.println(s.nthSuperUglyNumber(1000000, primes));
    }
}


 可能大家对p数组在这里的意义会有点不理解,p只是一个优化而已。uglys[i]是i前面某个数乘以某个素数,primes素组是免不了要遍历的,但uglys可以不用遍历啊,因为我们再求uglys[i-1]的时候已经验证了某个丑数即便是乘以任意一个给定的素数也不会大于uglys[i-1]的,这里我们需要维护一个性质,任意一个j使得p[j]*primes[j] > uglys[i-1]。

 多数一句,看下数据量,n最大是1000000,k最大是100,所以整个代码最内层循环最大应该是100m,这样算法能在几十毫秒解掉此题,看来leetcode的数据比较水。

目录
相关文章
|
3月前
|
Java Go C++
Golang每日一练(leetDay0092) 丑数 I\II Ugly Number i\ii
Golang每日一练(leetDay0092) 丑数 I\II Ugly Number i\ii
40 0
Golang每日一练(leetDay0092) 丑数 I\II Ugly Number i\ii
|
5月前
|
Java
Leetcode 372. Super Pow
真正的解法其实思路很简单,我随便举个例子就很容易理解了,假设要求(123^4567)%1337,只需要把这个幂式子分解成几个层次,然后把球模加到每一层中间就很容易计算出来了。
25 0
|
5月前
|
存储
Leetcode Single Number II (面试题推荐)
给你一个整数数组,每个元素出现了三次,但只有一个元素出现了一次,让你找出这个数,要求线性的时间复杂度,不使用额外空间。
21 0
LeetCode contest 190 5417. 定长子串中元音的最大数目 Maximum Number of Vowels in a Substring of Given Length
LeetCode contest 190 5417. 定长子串中元音的最大数目 Maximum Number of Vowels in a Substring of Given Length
LeetCode Contest 178-1365. 有多少小于当前数字的数字 How Many Numbers Are Smaller Than the Current Number
LeetCode Contest 178-1365. 有多少小于当前数字的数字 How Many Numbers Are Smaller Than the Current Number
LeetCode 136. 只出现一次的数字 Single Number
LeetCode 136. 只出现一次的数字 Single Number
|
30天前
|
机器学习/深度学习 算法
力扣刷题日常(一)
力扣刷题日常(一)
20 2
|
1月前
|
存储 索引
《LeetCode》—— LeetCode刷题日记
《LeetCode》—— LeetCode刷题日记
|
1月前
|
搜索推荐
《LeetCode》——LeetCode刷题日记3
《LeetCode》——LeetCode刷题日记3
|
1月前
|
容器
《LeetCode》——LeetCode刷题日记1
《LeetCode》——LeetCode刷题日记1