LeetCode-264. 丑数 II-Java-medium

17 篇文章 0 订阅
14 篇文章 0 订阅

题目链接

法一(动态规划 + 三指针)
    /**
     * 法一(动态规划 + 三指针)
     * 1. 思路
     * (1)因为丑数只包含质因数2、3、5,所以对于下个丑数来说,一定是前面某个丑数乘3、乘3或者乘5所得
     * (2)定义三个指针p2、p3、p5,它们指向的数只能乘 2、3、5
     * (3)在循环过程中,每次选取2*dp[p2]、3*dp[p3]、5*dp[p5]这三个数中结果最小的数,并且将对应的指针向前移动
     * (4)有效循环是n次,当循环结束后,dp数组中就按从小到大的顺序保存了丑数
     * 2. 动态规划
     * (1)dp[i]代表第i-1个丑数
     * (2)最小的丑数是1,因此dp[0]=1;
     * 3. 复杂度
     * (1)时间复杂度 O(n)
     * (2)空间复杂度 0(n)
     *
     * @param n
     * @return
     */
    public int nthUglyNumber(int n) {
        int[] dp = new int[n];
        dp[0] = 1; // 初始化dp数组
        int p2 = 0, p3 = 0, p5 = 0; // 初始化指针p2、p3、p5为0
        for (int i = 1; i < n; i++) {
            dp[i] = Math.min(2 * dp[p2], Math.min(3 * dp[p3], 5 * dp[p5]));
            if (dp[i] == 2 * dp[p2]) { // 说明前p2个丑数*2也不可能产生比i更大的丑数了,所以移动p2
                p2++;
            }
            if (dp[i] == 3 * dp[p3]) { // 说明前p3个丑数*3也不可能产生比i更大的丑数了,所以移动p3
                p3++;
            }
            if (dp[i] == 5 * dp[p5]) { // 说明前p5个丑数*5也不可能产生比i更大的丑数了,所以移动p5
                p5++;
            }
        }
        return dp[n - 1];
    }
法二(优先队列)
    /**
     * 法二(优先队列)
     * 1. 思路
     * (1)先创建一个优先队列,因为第一个丑数是1,所以把1加入优先队列
     * (2)接下来不断地取出优先队列的队头元素,再分别乘以2/3/5后依次入队,最终第n个取出的数即为答案
     * 2. 复杂度
     * (1)时间复杂度 O(nlogn)
     * (2)空间复杂度 0(n)
     *
     * @param n
     * @return
     */
    public int nthUglyNumber_2(int n) {
        PriorityQueue<Long> heap = new PriorityQueue<>();
        heap.add(1L);
        long front = 1L;
        while (n-- > 1) {
            heap.add(heap.peek() * 2);
            heap.add(heap.peek() * 3);
            heap.add(heap.peek() * 5);
            heap.poll();
            while (heap.peek() == front) { // 若本次取出的和上次取出的一样,则不计数
                heap.poll(); // 删除重复的
            }
            front = heap.peek();
        }
        return heap.peek().intValue();
    }
本地测试
        /**
         * 264. 丑数 II
         */
        lay.showTitle(264);
        Solution264 sol264 = new Solution264();
        System.out.println(sol264.nthUglyNumber(10));
        System.out.println(sol264.nthUglyNumber_2(10));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值