264. 丑数 II (JAVA)

给你一个整数 n ,请你找出并返回第 n 个 丑数 。

丑数 就是只包含质因数 2、3 和/或 5 的正整数。

 

示例 1:

输入:n = 10
输出:12
解释:[1, 2, 3, 4, 5, 6, 8, 9, 10, 12] 是由前 10 个丑数组成的序列。
示例 2:

输入:n = 1
输出:1
解释:1 通常被视为丑数。
 

提示:

1 <= n <= 1690

 

思路I:丑数都是由之前的数,与2,3,5相乘获得的 => 动态规划

class Solution {
    public int nthUglyNumber(int n) {
        int p2 = 1, p3 = 1, p5 = 1; //指向下一个给2、3、5相乘的丑数的位置
        int[] dp = new int[n+1]; 
        dp[1] = 1;
        for(int i = 2; i <= n; i++){
            dp[i] = Math.min(dp[p2]*2, Math.min(dp[p3]*3, dp[p5]*5));
            if(dp[i] == dp[p2]*2) {
                p2++;
            }
            if(dp[i] == dp[p3]*3) { //要用3个if,因为可能存在多个最小值,比如2*3,3*2都等于6
                p3++;
            }
            if(dp[i] == dp[p5]*5) {
                p5++;
            }
        }
        return dp[n];
    }
}

思路II:使用最小堆,每次将堆中的最小值出堆,出堆后将其*2, *3, *5的数入堆。Java中可以使用优先队列实现最小堆。

class Solution {
    public int nthUglyNumber(int n) {
        Queue<Integer> priorityQueue = new PriorityQueue<>();
        priorityQueue.add(1);
        int count = 0;
        int curNumber = 1;
        long nextNumber;

        while(!priorityQueue.isEmpty()){
            count++;
            curNumber = priorityQueue.peek();
            while(!priorityQueue.isEmpty() && priorityQueue.peek() == curNumber) {
                priorityQueue.remove();
            }

            if(count >= n){
                break;
            }

            nextNumber = (long)curNumber * 2;
            if(nextNumber == curNumber*2) { //防止溢出
                priorityQueue.add(curNumber*2);
            }
            nextNumber = (long)curNumber * 3;
            if(nextNumber == curNumber*3) {
                priorityQueue.add(curNumber*3);
            }
            nextNumber = (long)curNumber * 5;
            if(nextNumber == curNumber*5) {
                priorityQueue.add(curNumber*5);
            }
        }
        return curNumber;
    }
}

 

posted on 2022-05-15 14:25  joannae  阅读(49)  评论(0编辑  收藏  举报

导航