【LeetCode】264. Ugly Number II

题目

Write a program to find the n-th ugly number.

Ugly numbers are positive numbers whose prime factors only include 2, 3, 5. For example, 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers.

Note that 1 is typically treated as an ugly number.


思路

我的思路

构建了一个优先级队列,最小的数位于队头,每次取出队头元素,分别乘以2,3,5后压入队列。但这种做法无法判断重复,比如2*3=3*2=6,所以会出现两个6。 为了避免加入重复元素,又构建了一个map存放哪些数被加入了队列。

Hot解法

利用动态规划思想,创建3个变量分别记录2,3,5三个乘数的被乘数在ugly number队列中的位置。每次都将乘积结果最小的写入vector,并将该乘数对应的变量右移一位。判断是否重复时不可以用if..else..语句,应该将每个乘数都判断一次,确保没有重复。


代码

我的代码
int nthUglyNumber(int n) {
        if (n<=0) return -1;
        priority_queue<long, vector<long>, greater<long>> pq;
        pq.push(1);
        unordered_map<long,bool> map;
        long top;
        unsigned int pri[3]={2,3,5};
        while (--n){
            top=pq.top();
            pq.pop();
            for (unsigned int i=0;i<3;++i){
                long cur = top*pri[i];
                if (!map[cur]){
                    pq.push(cur);
                    map[cur]=true;
                }
            }
        }
        return pq.top();
    }
Hot 解法
int nthUglyNumber(int n) {
        if (n<=0) return -1;
        vector<int> q(n);
        int t2(0),t3(0),t5(0);
        q[0]=1;
        for (int i=1;i<n;++i){
            q[i]=min(q[t2]*2,min(q[t3]*3,q[t5]*5));
            if (q[i]==q[t2]*2) ++t2;
            if (q[i]==q[t3]*3) ++t3;
            if (q[i]==q[t5]*5) ++t5;
        }
        return q[n-1];
    }

优先队列

在我的代码中,运用到了优先队列priority_queue这种数据结构,首先它的基本操作和队列有所不同,队列中队头是front(),而它是top(),其余的push,pop基本一样。

priority_ queue构造参数有三个,priority_queue<Type, Container, Functional>Type 为数据类型, Container 为保存数据的容器,Functional 为元素比较方式。默认只写一个参数即可,但是比较函数默认为less,也就是最大数排在队头

若想让最小数排在队头,那么需要这么写

#include <iostream>  
#include <queue>  
using namespace std;  
int main(){  
    priority_queue<int,vector<int>,greater<int> >q;  
    for(int i=0;i<10;i++)   
        q.push(i);  
    while(!q.empty()){  
        cout<<q.top()<< endl;  
        q.pop();  
    }  
    return 0;  
}  

如果队列中存的是自定义类型,那么有两种写法:

#include <iostream>  
#include <queue>  
using namespace std;  
struct Node{  
    int x, y;  
}node;  
 bool operator<( Node a, Node b){  
    if(a.x==b.x) return a.y>b.y;  
    return a.x>b.x;  
}  
 int main(){  
    priority_queue<Node>q;  
    for(int i=0;i<10;i++){  
        node.x=i;  
        node.y=10-i/2;  
        q.push(node);  
    }     
    while(!q.empty()){  
        cout<<q.top().x <<' '<<q.top().y<<endl;  
        q.pop();  
    }  
    return 0;  
}  

或是

#include <iostream>  
#include <queue>  
using namespace std;  
struct Node{  
    int x, y;  
}node;  
struct cmp{  
    bool operator()(Node a,Node b){  
        if(a.x==b.x) return a.y>b.y;  
        return a.x>b.x;}  
};  

 int main(){  
    priority_queue<Node,vector<Node>,cmp>q;  
    for(int i=0;i<10;i++){  
        node.x=i;  
        node.y=10-i/2;  
        q.push(node);     
    }     
    while(!q.empty()){  
        cout<<q.top().x<<' '<<q.top().y<<endl;  
        q.pop();  
    }  
    return 0;  
}  

个人比较推荐第二种方式, 因为比较通用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值