把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

思路跟书上一样:

class Solution {
public:
    int GetUglyNumber_Solution(int index) {
        if (index <= 0)
            return 0;
        //因为丑数的前5个数是1,2,3,4,5,所以可直接返回
        if (index > 0 && index <= 5)
            return index;
        vector<int> sequenceUgly = { 1,2,3,4,5 };
        return getUglyNumber(sequenceUgly, index);
    }
    //递归获得有序丑数数组
    int getUglyNumber(vector<int>& sequenceUgly, int index)
    {
        int uglySize = sequenceUgly.size();
        //若丑数数列达到要求长度,停止递归,返回尾部值即为所求
        if (uglySize == index)
            return sequenceUgly[uglySize - 1];
        //M是原丑数数列中最大的一个数
        int M = sequenceUgly[uglySize - 1];
        //M2s是丑数数列乘以2之后,第一个大于M的数,M3,M5同理
        int M2 = getMax(sequenceUgly, 2, M);
        int M3 = getMax(sequenceUgly, 3, M);
        int M5 = getMax(sequenceUgly, 5, M);
        //求出M2,M3,M5中最小的一个数
        int minM = min(M2, M3);
        if (minM > M5)
            minM = M5;
        sequenceUgly.push_back(minM);
        //cout << "minM: " << minM << endl;
        return getUglyNumber(sequenceUgly, index);
    }

    //丑数数列中的数乘以data(2/3/5)后,挑选出大于M的第一个数返回
    int getMax(vector<int>& sequenceUgly, int data, int M)
    {
        vector<int> duplicateUgly(sequenceUgly);
        for (int i = 0; i < duplicateUgly.size(); ++i)
        {
            duplicateUgly[i] = duplicateUgly[i] * data;
        }
        int j = 0;
        while (j<duplicateUgly.size()&&duplicateUgly[j]<=M)
        {
            ++j;
        }
        return duplicateUgly[j];
    }
};

这里没有用那种逐个判断每个整数是否是丑数的方法,但还是贴上判断整数n是否为丑数的代码:

bool isUgly(int n)
{
    while (n % 2 == 0)
        n = n / 2;
    while (n % 3 == 0)
        n = n / 3;
    while (n % 5 == 0)
        n = n / 5;
    return (n == 1) ? true : false;
}