1. 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.

Example:

Input: n = 10
Output: 12
Explanation: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 is the sequence of the first 10 ugly numbers.

Note:

  1. 1 is typically treated as an ugly number.
  2. n does not exceed 1690.

解法1

暴力搜索。假设已经知道了前n个丑数\(a_1, a_2, ..., a_n\),求第n+1个丑数,则有:

\[a_{n+1} = \min\{2*a_i, 3*a_j, 5*a_k\}, \quad \forall i, j, k\in[1, n]\\
s.t\quad a_{n+1} > a_n
\]
class Solution {
public:
int nthUglyNumber(int n) {
vector<int>u_n{1};
int prime[3] = {2, 3, 5};
while(u_n.size() < n){
int flag = 0;
int cur_n = INT_MAX;
for(int i = u_n.size() - 1; i >= 0; --i){
for(int j = 0; j < 3; ++j){
if(u_n[i]*prime[j] > u_n.back()){
cur_n = min(cur_n, u_n[i]*prime[j]);
}else{
flag++;
}
}
if(flag == 3)break;
}
u_n.push_back(cur_n);
}
return u_n.back();
}
};

但是提交会超时。。。

解法2 对解法1进行改进。显然丑数数组是有序的,可以用二分查找完成,查找的问题描述为:

寻找第一次出现的满足 \(k\times a_i > a_n\)的\(a_i\)

搜索过程为:对于区间\([l, r]\)

  • \(k\times a_{mid} > a_n\),则满足条件的肯定在\([l, mid]\)中
  • \(k\times a_{mid} \leq a_n\),则满足条件的肯定在\([mid+1, r]\)中
typedef long long int LL;
class Solution {
public:
int nthUglyNumber(int n) {
vector<LL>u_n{1};
int prime[3] = {2, 3, 5};
while(u_n.size() < n){
LL cur_n = LLONG_MAX;
for(int j = 0; j < 3; ++j){
int idx = bin_search(u_n, prime[j]);
cur_n = min(cur_n, prime[j]*u_n[idx]);
}
u_n.push_back(cur_n);
}
return u_n.back();
}
int bin_search(vector<LL>&nums, int k){
int last_num = nums.back();
int l = 0, r = nums.size()-1;
while(l < r){
int mid = (l + r) / 2;
if(nums[mid]*k > last_num)r=mid;
else l = mid + 1;
}
return l;
}
};

解法3 注意到事实:如果\(a_n\)是丑数,则\(2a_n, 3a_n, 5a_n\)也是丑数

typedef long long int LL;
class Solution {
public:
int nthUglyNumber(int n) {
priority_queue<LL, vector<LL>, greater<LL>>q;
set<LL>s;
int prime[3] = {2, 3, 5}; q.push(1);
s.insert(1);
LL ans = q.top();
for(int i = 0; i < n; ++i){
ans = q.top();
q.pop();
s.erase(ans);
for(int j = 0; j < 3; ++j){
if(s.find(ans*prime[j]) == s.end()){
q.push(ans*prime[j]);
s.insert(ans*prime[j]);
}
}
}
return ans;
}
};

解法4 根据解法三种事实,利用动态规划

class Solution {
public:
int nthUglyNumber(int n) {
int pre2 = 0, pre3 = 0, pre5 = 0;
int nums[1690];
nums[0] = 1;
for(int i = 1; i < n; ++i){
int ugly = min(nums[pre2]*2, min(nums[pre3]*3, nums[pre5]*5));
nums[i] = ugly;
if(ugly % 2 == 0)pre2++;
if(ugly % 3 == 0)pre3++;
if(ugly % 5 == 0)pre5++;
}
return nums[n-1];
}
};

最新文章

  1. C# 通过WebService方式 IIS发布网站 上传文件到服务器
  2. 4KB对齐
  3. java抽象类的使用
  4. Android编程: ViewPager和Dialogs组件
  5. 文件重定向函数freopen
  6. JavaScript高级程序设计(第三版)第二章 在HTML中使用JavaScript
  7. Windows使用virtualenv搭建flask开发环境
  8. [MarsZ]程序猿谈大学之大学应该学好哪些课程
  9. 密码算法详解——AES
  10. 从头开始学JavaScript (十三)——Date类型
  11. Node填坑教程——简易http服务器
  12. [M]表格中的天正文字转换问题
  13. nginx的location优先级
  14. [Swift]LeetCode664. 奇怪的打印机 | Strange Printer
  15. JavaSE基础知识(5)—面向对象(对象数组和对象关联)
  16. ue4 蓝图方法备份
  17. 10.23 crm(3)
  18. AMI:加密的机器映像。卷
  19. C# 数值类型和无穷大
  20. 在Linux上实现SVN用户密码自助修改

热门文章

  1. Android4.4开机动画播放视频
  2. 【C语言】Socket发送HTTP-TCP请求,数据有字符串插入
  3. X-Tim开发日志
  4. 注解版mybatis动态语句将空字符串转换为null
  5. Linux(centos)安装es(elasticsearch)
  6. 【LeetCode】279. Perfect Squares 解题报告(C++ & Java)
  7. 【LeetCode】536. Construct Binary Tree from String 解题报告(C++)
  8. 【LeetCode】676. Implement Magic Dictionary 解题报告(Python & C++)
  9. ZOJ 3785:What day is that day?(数论)
  10. Consistency Regularization for GANs