1. 程式人生 > >Leetcode313:超級醜數

Leetcode313:超級醜數

編寫一段程式來查詢第 n 個超級醜數。

超級醜數是指其所有質因數都是長度為 k 的質數列表 primes 中的正整數。

示例:

輸入: n = 12, primes = [2,7,13,19]
輸出: 32 
解釋: 給定長度為 4 的質數列表 primes = [2,7,13,19],前 12 個超級醜數序列為:[1,2,4,7,8,13,14,16,19,26,28,32] 。

解題思路:

多指標法。

  1. 假設素數的個數是nums,那麼就分配nums個指標,它們的屬性是primes[i],使得每個指標對應它們指向第k個素數。初始時刻所有指標都指向1,第0個素數。
  2. 下一個醜數必然是這nums個指標指向的數分別乘以它們的屬性,然後在nums個數字中取最小值min。
  3. 這些指標中,所有計算結果等於min的都必須向後移動一個單位,否則下一次計算就會小於當前得到的醜數。
  4. 由此可見等待計算的數字不可能超過nums個,因此複雜度為O(n*nums)。
C++程式碼標準版
class Solution {
public:
    int nthSuperUglyNumber(int n, vector<int>& primes) {
        int size = primes.size(), i, j;
        vector<int> sgn(size, 0);
        vector<int> ret(1, 1);
        for (i = 1; i < n; i++) {
            int minVal = INT_MAX;
            vector<int> move;
            for (j = 1; j <= size; j++) {
                int newdata = ret[sgn[j - 1]] * primes[j - 1];
                if (newdata == minVal) move.push_back(j);
                else if(newdata<minVal){ 
                    move.clear(); 
                    move.push_back(j);
                }
                minVal = min(minVal, ret[sgn[j - 1]] * primes[j - 1]);
            }
            ret.push_back(minVal);
            for (j = 1; j <= int(move.size()); j++) {
                sgn[move[j - 1] - 1]++;
            }
        }
        return ret.back();
    }
};

 

C++程式碼優化版

class Solution {

public:

int nthSuperUglyNumber(int n, vector<int>& primes) {

if (n == 1) return 1;

int l = primes.size();

vector<int> ugly(n,INT_MAX);

vector<int> tmp(l,1);

vector<int> count(l,0);

int next = 1; for (int i = 0; i < n; i++) {

ugly[i] = next;

next = INT_MAX;

for (int j = 0; j < l; j++) {

if (tmp[j] == ugly[i]) {

tmp[j] = ugly[count[j]]*primes[j]; count[j]++;

}

next = min(next,tmp[j]);

}

}

return ugly[n-1];

}

};