313. Super Ugly Number

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();
}

猜你喜欢

转载自blog.csdn.net/qq_34229391/article/details/81951926
今日推荐