丑数

int nthUglyNumber(int n) {
    // 每个因子x对应一个要相乘的已知丑数seq[ix],以生成下个丑数 min{ seq[ix]*x }
    // 当生成了下个丑数后,所有参与生成的因子的索引ix++
    vector<int> seq;
    seq.push_back(1);
    int i2 = 0, i3 = 0, i5 = 0;
    for (int i = 1; i < n; i++) {
        int next = min({ seq[i2] * 2, seq[i3] * 3, seq[i5] * 5 });
        seq.push_back(next);
        if (next == seq[i2] * 2) i2++;
        if (next == seq[i3] * 3) i3++;
        if (next == seq[i5] * 5) i5++;
    }
    return seq.back();
}

超级丑数

上面算法的扩展

int nthSuperUglyNumber(int n, vector<int>& primes) {
    vector<int> seq;
    seq.push_back(1);
    // 每个因子对应有一个要相乘的已知丑数,以生成下个丑数
    // 第j个因子primes[j]对应的丑数是seq[idx[j]]
    const int M = primes.size();
    vector<int> idx(M, 0); 
    for (int i = 1; i < n; i++) {
        int next = INT_MAX;
        for (int j = 0; j < M; j++) {
            next = min(next, seq[idx[j]] * primes[j]);
        }
        seq.push_back(next);
        for (int j = 0; j < M; j++) {
            if (next == seq[idx[j]] * primes[j]) idx[j]++;
        }
    }
    return seq.back();
}

注意:丑数可以无限生成下去,因此不是在行列有序的矩阵中找第k小数的问题。