超级丑数(Super Ugly Number)

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 算法题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值