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的数据比较水。

目录
相关文章
|
6月前
|
存储 SQL 算法
LeetCode 题目 65:有效数字(Valid Number)【python】
LeetCode 题目 65:有效数字(Valid Number)【python】
|
7月前
|
存储 算法
【LeetCode力扣】单调栈解决Next Greater Number(下一个更大值)问题
【LeetCode力扣】单调栈解决Next Greater Number(下一个更大值)问题
52 0
|
7月前
|
Java Go C++
Golang每日一练(leetDay0092) 丑数 I\II Ugly Number i\ii
Golang每日一练(leetDay0092) 丑数 I\II Ugly Number i\ii
76 0
Golang每日一练(leetDay0092) 丑数 I\II Ugly Number i\ii
|
Java
Leetcode 372. Super Pow
真正的解法其实思路很简单,我随便举个例子就很容易理解了,假设要求(123^4567)%1337,只需要把这个幂式子分解成几个层次,然后把球模加到每一层中间就很容易计算出来了。
44 0
|
存储
Leetcode Single Number II (面试题推荐)
给你一个整数数组,每个元素出现了三次,但只有一个元素出现了一次,让你找出这个数,要求线性的时间复杂度,不使用额外空间。
39 0
|
3月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
4月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
61 6
|
4月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
123 2
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
280页PDF,全方位评估OpenAI o1,Leetcode刷题准确率竟这么高
【10月更文挑战第24天】近年来,OpenAI的o1模型在大型语言模型(LLMs)中脱颖而出,展现出卓越的推理能力和知识整合能力。基于Transformer架构,o1模型采用了链式思维和强化学习等先进技术,显著提升了其在编程竞赛、医学影像报告生成、数学问题解决、自然语言推理和芯片设计等领域的表现。本文将全面评估o1模型的性能及其对AI研究和应用的潜在影响。
40 1
|
3月前
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口