这是一个常见的面试题目,关于什么是丑数,可以百度搜索。
一种常见的思维是数字往前累加,判断是否是丑数,最后得出第N个丑数。
另一思路是把已找到的数字作为基础数据,在已有的数据之后,找出一个比当前已找出的最大数要大的第1个丑数。
下面是实现代码,可直接运行:
package com.kittaaron.algorithm;
import java.util.Arrays;
/**
* @author kittaaron
* created by 2/18/20
*/
public class GetUglyNum {
public static void main(String[] args) {
int i = 1500;
long firstStart = System.currentTimeMillis();
findIthUglyByIncre(i);
long firstEnd = System.currentTimeMillis();
findIthUglyByCalc(i);
long secondEnd = System.currentTimeMillis();
System.out.println("算法1耗时:" + (firstEnd - firstStart) + "毫秒.");
System.out.println("算法2耗时:" + (secondEnd - firstEnd) + "毫秒.");
}
private static void findIthUglyByIncre(long i) {
long cnt = 0, start = 0;
while(true) {
start++;
if (isUgly(start)) {
cnt++;
}
if (cnt == i) {
break;
}
}
// 寻找第i个丑数
System.out.println("第" + i + "个丑数是:" + start);
}
private static boolean isUgly(long num) {
while (num % 2 == 0) {
num /= 2;
}
while (num % 3 == 0) {
num /= 3;
}
while (num % 5 == 0) {
num /= 5;
}
return num == 1;
}
private static long findIthUglyByCalc(int i) {
// ugArr为已经找出的丑数数组
long firstUgly = 1;
long[] arr = new long[i];
arr[0] = firstUgly;
int currentIdx = 0;
while(currentIdx < i-1) {
findNextUgly(arr, currentIdx);
currentIdx++;
}
System.out.println("高效方法找到第" + i + "个丑数:" + arr[i-1]);
//System.out.println("所有丑数:" + Arrays.toString(arr));
return arr[i-1];
}
private static void findNextUgly(long[] arr, int currentMaxIdx) {
long currentMax = arr[currentMaxIdx];
// 从已找出来的数往前推,每个数字*2,如果比当前已找出的最大还大,继续往前推
int tmp = currentMaxIdx;
while (arr[tmp] * 2 > currentMax) {
tmp--;
if (tmp < 0) break;
}
long nextMulti2 = arr[tmp+1] * 2;
// 从已找出来的数往前推,每个数字*3,如果比当前已找出的最大还大,继续往前推
tmp = currentMaxIdx;
while (arr[tmp] * 3 > currentMax) {
tmp--;
if (tmp < 0) break;
}
long nextMulti3 = arr[tmp+1] * 3;
// 从已找出来的数往前推,每个数字*5,如果比当前已找出的最大还大,继续往前推
tmp = currentMaxIdx;
while (arr[tmp] * 5 > currentMax) {
tmp--;
if (tmp < 0) break;
}
long nextMulti5 = arr[tmp+1] * 5;
long least = findLeast(nextMulti2, nextMulti3, nextMulti5);
arr[currentMaxIdx+1] = least;
}
private static long findLeast(long i, long j, long k) {
return i > j ? Math.min(j, k) : Math.min(i, k);
}
}
本地运行结果如下:
第1500个丑数是:859963392
高效方法找到第1500个丑数:859963392
算法1耗时:12079毫秒.
算法2耗时:19毫秒.
网友评论