Question:
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.
Note:
(1) 1 is a super ugly number for any given primes.
(2) The given numbers in primes are in ascending order.
(3) 0 < k ≤ 100, 0 < n ≤ 10^6, 0 < primes[i] < 1000.
简单地说,这个问题就是要找出第n个超级丑数。超级丑数确实比丑数更加讨厌,是丑数的升级版,可以简单地理解为是丑数的一般形式。给定一个维数为k的素数序列primes
。超级丑数就是它的因子只能是primes
中的若干个元素。丑数的因子只有2,3,5,所以将丑数推广到一般形式就是超级丑数了。在丑数II中的解决的算法推广一下,就可以用来解决这个问题了。算法如下:
Nth-Super-Ugly-Number(n, PRIMES)
1. if n <= 0 or PRIMES size <= 0
2. return -1
3. let PRIMES_LOCATION be the array with the same size as PRIMES
4. for i = 0 to PRIMES.size -1
5. PRIME_LOCATION[i] = 0
6. let UGLY_NUM be the array with the size of n
7. UGLY_NUM[0] = 1
8. for i = 1 to n-1
9. min = UGLY_NUM[PRIMES_LOCATION[0]]*PRIMES[0]
10. for j = 1 to PRIMES.size -1
11. if UGLY_NUM[PRIMES_LOCATION[j]]*PRIMES[j]
12. min = UGLY_NUM[PRIMES_LOCATION[j]]*PRIMES[j]
13. UGLY_NUM[i] = min
14. for j = 0 to PRIMES.size -1
15. if min == UGLY_NUM[PRIMES_LOCATION[j]]*PRIMES[j]
16. PRIMES_LOCATION[j] += 1
17. return UGLY_NUM[n-1]
算法大致的思路和丑数II的算法一致。只是第3行多了一个数组来存储素数所指的位置,如在丑数II中的U2,U3和U5的位置。第8~16行是找出第i个超级丑数。相应的Java语言实现和Swift语言实现如下。
Java语言实现:
public class Solution {
public int nthSuperUglyNumber(int n, int[] primes) {
if (n <= 0 || primes == null || primes.length == 0)
return -1;
int lengthOfPrime = primes.length;
//to indicate the location in the uglyNum of each prime
int[] primeLocation = new int[lengthOfPrime];
for (int i = 0; i < lengthOfPrime; i++)
// set all the location to indicate the first location
primeLocation[i] = 0;
int[] uglyNum = new int[n];
uglyNum[0] = 1;
for (int i = 1; i < n; i++) {
int min = uglyNum[primeLocation[0]] * primes[0];
for (int j = 1; j < lengthOfPrime; j++) {
if (uglyNum[primeLocation[j]] * primes[j] < min) {
min = uglyNum[primeLocation[j]] * primes[j];
}
}
for(int j = 0; j < lengthOfPrime; j ++){
if(uglyNum[primeLocation[j]] * primes[j] == min){
primeLocation[j] += 1;
}
}
uglyNum[i] = min;
}
System.out.println(Arrays.toString(uglyNum));
return uglyNum[n - 1];
}
}
Swift语言实现:
import Foundation
func nthSuperUglyNumber(n: Int, _ primes: [Int]) -> Int {
if n <= 0 || primes.count == 0 {
return -1
}
if n == 1{
return 1
}
let primesSize = primes.count
var primesLocation: [Int] = Array(count: primesSize, repeatedValue: 0)
var uglyNums: [Int] = Array(count: n, repeatedValue: 0)
uglyNums[0] = 1
for i in 1..<n {
var min = uglyNums[primesLocation[0]] * primes[0]
for j in 1 ..< primesSize {
if uglyNums[primesLocation[j]]*primes[j] < min {
min = uglyNums[primesLocation[j]]*primes[j]
}
}
for j in 0 ..< primesSize {
if uglyNums[primesLocation[j]]*primes[j] == min {
primesLocation[j] += 1
}
}
uglyNums[i] = min
}
return uglyNums[n-1]
}
参考:
LeetCode 算法题