寻找第1500个丑数(JAVA代码)

这是一个常见的面试题目,关于什么是丑数,可以百度搜索。

一种常见的思维是数字往前累加,判断是否是丑数,最后得出第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毫秒.

你可能感兴趣的:(寻找第1500个丑数(JAVA代码))