LeetCode 264. 丑数 II 优先队列(小根堆) 动态规划

该博客介绍了如何利用小根堆和哈希表来解决寻找第n个丑数的问题。首先建立包含1的优先队列,然后在堆中取出最小元素,与2,3,5相乘并查重,将不重复的乘积加入堆中。通过这种方法,可以以O(nlogn)的时间复杂度和O(n)的空间复杂度找到第n个丑数。此外,还对比了暴力求解和动态规划的方法。
摘要由CSDN通过智能技术生成

丑数

题目连接:(这俩都一样)

264. 丑数 II

剑指 Offer 49. 丑数

题目

———————————————————————————————————————————

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

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

示例 1

输入:n = 10

输出:12

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

示例 2

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

提示:

  • 1 <= n <= 1690

———————————————————————————————————————————

小根堆(用到java的优先队列)+哈希

关键点:

1:建堆:建立起优先队列,初始添加元素1

2:取数:每次取出队列的堆头,再把取出的数依次乘上2,3,5后查重并调用offer插入形成小根堆

3:查重:有了新的堆元素,需要判断重复的元素,就需要用到哈希hashSet

4:计数:统计取对头的次数

时间复杂度:O(nlogn)

空间复杂度:O(n)

代码:

class Solution {
public int nthUglyNumber(int n) {
		//定义三个质因数2,3,5
        int[] factors = {2, 3, 5};
		//创建一个哈希表后面用于查重
// import java.util.HashSet;
//import java.util.Set;
        Set<Long> seen = new HashSet<Long>();
//创建一个优先队列
//import java.util.PriorityQueue;
        PriorityQueue<Long> heap = new PriorityQueue<Long>();
		//把初始根1加入哈希表和小顶堆中(long型要写为1L)
//调用 offer()方法后,往堆中压入元素然后从下往上调整堆为小顶堆。
        seen.add(1L);
        heap.offer(1L);
        int ugly;
        for (int i = 0; i < n; i++) 
{
//取出并删处根节点的丑数。
//poll 方法每次从 PriorityQueue 的头部删除一个节点
            long curr = heap.poll();
            ugly = (int) curr;
			//取每个质因数乘以根节点,如果没有重复,插入小顶堆
            for (int factor : factors) {
                long next = curr * factor;
				//如果没有重复,加入哈希表
                if (seen.add(next)) {
				//插入丑数,并调整为小顶堆
                    heap.offer(next);
                }
            }
        }
        return ugly;
    }
}

注:

1.优先队列的逻辑结构是一棵完全二叉树,存储结构其实是一个数组。

逻辑结构层次遍历的结果刚好是一个数组

2.offer方法:往堆中压入元素然后从下往上调整堆为小顶堆。

3.poll方法:在堆中每次删除只能删除头节点,并将最后一个节点替代头节点然后进行调整。

优先队列其他方法详解链接:

Java堆结构PriorityQueue完全解析

其他方法:

1.暴力(超时)

int nthUglyNumber(int n){
//使用双层循环去表遍历对应的数是否为丑数
//直接超时
int count= 0;// 统计目标值
for(i =1; i< INT_MAX;i++) //枚举
{
 	  	int m = i;
		while (n % 2 == 0) {m /= 2;}
		while (n % 3 == 0) {m /= 3;}
		while (n % 5 == 0) {m /= 5;}
if(m == 1) {count++; }
if(count == n){return m;}
}
}

2.动态规划(我觉得比小根堆简单)

原理:

题解链接 剑指 Offer 49. 丑数(动态规划,清晰图解)

代码:

class Solution {
    public int nthUglyNumber(int n) {
        int a = 0, b = 0, c = 0;
        int[] dp = new int[n];
        dp[0] = 1;
        for(int i = 1; i < n; i++) {
            int n2 = dp[a] * 2, n3 = dp[b] * 3, n5 = dp[c] * 5;
            dp[i] = Math.min(Math.min(n2, n3), n5);
            if(dp[i] == n2) a++;
            if(dp[i] == n3) b++;
            if(dp[i] == n5) c++;
        }
        return dp[n - 1];
    }
}

进阶题目链接:

1201. 丑数 III

313. 超级丑数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值