剑指Offer-题49(Java版):丑数

参考自:《剑指Offer——名企面试官精讲典型编程题》

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

主要思路:需要保存和利用之前已经找到的丑数,并使这些丑数按从小到大排序。关键在于,找出三个已存在的丑数,分别乘以因子2,3,5,生成三个新丑数,使得这三个新丑数刚刚大于已在数组中的所有丑数,然后新的丑数就是这三个丑数中最小的那个。可以使用三个变量来记录每个因子对应的已存在的丑数位置,每次找出新丑数后,都更新对应的记录变量。

关键点:保存和利用已存在的丑数

时间复杂度:O(n)

public class UglyNumber
{
    public static void main(String[] args)
    {
        System.out.println(getUglyNumberAt(10)); //12
        System.out.println(getUglyNumberAt(11)); //15
        System.out.println(getUglyNumberAt(1500)); //859963392
    }

    private static int getUglyNumberAt(int index)
    {
        if (index < 1) return 0;
        if (index < 7) return index;

        int[] records = new int[index];  //从小到大记录丑数
        records[0] = 1;
        //2, 3, 5对应的丑数位置,初始化为第一个
        int indexFor2 = 0;
        int indexFor3 = 0;
        int indexFor5 = 0;
        for (int i = 1; i < index; i++)
        {
            //已知的丑数乘以因子2, 3, 5,
            //使得这三个新丑数刚刚大于已在数组中的所有丑数
            int product2 = records[indexFor2] * 2;
            int product3 = records[indexFor3] * 3;
            int product5 = records[indexFor5] * 5;
            //找出三个新丑数中最小的
            int min = getMin(product2, product3, product5);
            records[i] = min;
            //更新2, 3, 5相应的丑数位置,min可能等于多个新丑数,所以不能用else
            if (product2 == min) indexFor2++;
            if (product3 == min) indexFor3++;
            if (product5 == min) indexFor5++;
        }
        return records[index - 1];
    }

    private static int getMin(int a, int b, int c)
    {
        int result = a;
        if (b < result) result = b;
        if (c < result) result = c;
        return result;
    }
}

猜你喜欢

转载自blog.csdn.net/m0_37862405/article/details/80369282