参考自:《剑指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;
}
}