313. Super Ugly Number

本文介绍了一种算法,用于寻找第n个超级丑数。超级丑数是指所有质因数都在给定质数列表中的正整数。文章提供了两种实现方式,一种使用set进行排序,另一种使用基本数据类型优化效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.

Example:

Input: n = 12, primes = [2,7,13,19]
Output: 32
Explanation: [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.

Note:

    1 is a super ugly number for any given primes.
    The given numbers in primes are in ascending order.
    0 < k ≤ 100, 0 < n ≤ 10^6, 0 < primes[i] < 1000.
    The nth super ugly number is guaranteed to fit in a 32-bit signed integer.

之前做过一道题是Ugly Number II,这道题是按照顺序找出第n个质数因子在2,3,5这个集合中的数字。

做法是利用2,3,5这三个数互乘,并按照大小排好次序,并返回第n个数字,顺序如下2,3,4,5,6,8,9,10.....

那么是否存在某一个数的质数因子全都是2,3,5这个集合中的,但是又不能通过这三个数互乘得到呢,加入存在这样这一个数N,那么N=A*B,A和B中A为质数,A是2,3,5中的一个,B不是一个质数,那么B可以分解为E和F,即B=E*F,那么如果E,F中,E为质数,那么N=A*B=(A*F)*E,因为A的质数因子属于{2,3,5},所以E属于{2,3,5},同样,如果F为一个质数也必然属于{2,3,5},如果F为一个合数,那么它的所有因子也都属于{2,3,5},否则的话,就不能满足A的所有质数因子都属于{2,3,5}这个条件。

那么我们就利用2,3,5这三个数字互乘,得到所有的可能,并按照大小顺序排好,最终得到第n项。

明白了Ugly Number II,那么Super Ugly Number也可以直接做了,不过使用不同的数据结构,耗时差异很大,下面的代码使用的是set,利用set的自动排序,但是差点超时。

int nthSuperUglyNumber(int n, vector<int>& primes)
{
	if (n == 1)return 1;
	vector<int> nums;
	nums.push_back(1);
	vector<int> list(primes.size(), 0);
	set<int> se;
	while (nums.size() < n)
	{
		se.clear();
		for (int i = 0; i < primes.size(); i++)se.insert(nums[list[i]] * primes[i]);
		if (*(se.begin()) != nums.back())nums.push_back(*(se.begin()));
		for (int i = 0; i < list.size(); i++)if (nums.back() == nums[list[i]] * primes[i]){list[i]++; break;}
	}
	return nums.back();
}

下面的代码使用的基本数据类型,速度比上面的快上很多。

int nthSuperUglyNumber(int n, vector<int>& primes)
{
	if (n == 1)return 1;
	vector<int> nums;
	nums.push_back(1);
	vector<int> list(primes.size(), 0);
	while (nums.size() < n)
	{
		int temp = INT_MAX;
		for (int i = 0; i < primes.size(); i++)temp = min(temp, nums[list[i]] * primes[i]);
		if(nums.back() != temp)nums.push_back(temp);
		for (int i = 0; i < list.size(); i++)if (nums.back() == nums[list[i]] * primes[i]) { list[i]++; break; }
	}
	return nums.back();
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值