优先队列Uva136:丑数(Ugly Numbers)

文章介绍了如何利用优先队列(基于堆排序的结构)来解决寻找第1500个不能被2,3,5以外的素数整除的数(丑数)的问题。通过创建一个优先队列,不断生成并检查新丑数,避免了大数量级时的空间和时间浪费。代码示例使用C++实现,展示了如何避免重复并有效地找到目标丑数。
摘要由CSDN通过智能技术生成

一、题目

丑数是指不能被2,3,5以外的其他素数整除的数。把丑数从小到大排列起来,结果如
下:
1,2,3,4,5,6,8,9,10,12,15,…
求第1500个丑数。

答案:859963392

二、优先队列说明

优先队列本质上是堆排序,虽然说是按照优先级来排序,但是对于单纯的数字集合来说,就是简单的按照从小到大或者从大到小的顺序排序。

priority_queue <int>//默认从小到大,当然int可以换成其他的数据类型,下面的也是类似的
priority_queue <int,vector<int>,less<int> > q;//按照从大到小排序
priority_queue <int,vector<int>,greater<int> > q;//按照从小到大排序

还有一些队列的基本操作

q.size();//返回q的元素个数
q.empty();//判断q是否为空,空则返回1,否则返回0
q.push(k);//在q的末尾插入k
q.pop();//删除q的第一个元素
q.top();//返回q的第一个元素

vector是队列内部用于承载底层数据结构堆的容器,less是对第一个参数的比较类。
那这个优先级具体在项目上面有什么作用呢?比如你是开蔬菜店的,就可以用优先队列优先出售价格低的啊,新鲜的蔬菜啊等等。

三、思路分析

本题解法很多,但是第一情况下,大家是不是会想到一个数一个数的循环遍历,并用一个变量(sum)记录,如果是能被2,3,5整除的素数,看sum是否等于第1500,到了就输出那个数。
**注意:**这种方法固然没有问题,但是如果数据量过大,让你求第好几亿个呢,得用多少空间,多少时间呢?因此我们在写算法的时候需要考虑题目要求的时间空间限制。这题可以用优先队列解决。
解题优化思路: 最小的丑数是1,其他所有数x,2x,3x,4x,5x都是丑数,如果用一个优先队列保存所有已生成的丑数,每次把最小的丑数取出来,然后生成三个新的丑数。但有一点要注意,在生成过程中难免会产生几个数的公倍数,所以得用set数组的不允许有重复元素的特性,用count()方法判断是否已经生成过。

四、代码

#include<iostream>
#include<vector>
#include<queue>
#include<set>
typedef long long ll;
const int a[3] = { 2, 3, 5 };
using namespace std;

int main() {
	priority_queue<ll, vector<ll>, greater<ll> > pq;		//创造一个优先队列,默认按照从小到大排序
	set<ll> s;
	pq.push(1);					//先向集合和队列里面存入第一个丑数1,有了第一个数就是不断生成新的丑数。
	s.insert(1);				//设置一个set集合,保证之后的元素没有重复的
	for (int i = 1; ; i++) {
		ll x = pq.top();		//获取队列的第一个元素
		pq.pop();				//踢掉第一个元素
		if (i == 1500) {
			cout << "第1500个数是: " << x << endl;
			break;
		}
		for (int j = 0; j < 3; j++) {	//用这个数分别乘以2,3,5,得到三个新的丑数,和之前的数作比较,如果没有出现过,就假如集合
			ll x1 = x * a[j];
			if (!s.count(x1)) {
				s.insert(x1);
				pq.push(x1);
			}
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值